Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I want to test that a method adds a record to a DBSet under a certain condition:

public static void AddTriggeredInternalTransactions(IDataContext dc, ExternalTransaction transaction)
{
    if (transaction [meets condition A])
        dc.InternalTransactions.CreateInverseTransaction(transaction);

    // do other stuff under other conditions
}

private static void CreateInverseTransaction(this IDbSet<InternalTransaction> transactions, ExternalTransaction from)
{
    var internalTransaction = transactions.Create();
    from.CopyToInternalTransaction(internalTransaction);
    transactions.Add(internalTransaction);
}

Now, I already have tests for CopyToInternalTransaction(). I just need to call AddTriggeredInternalTransactions() and verify that [condition A] results in the new record being added).

I started with http://msdn.microsoft.com/en-us/data/dn314429.aspx, then used other Google and StackOverflow searches. Before tackling my "real" test, I'm trying to do a simple test just to verify whether a record has been added to a dataset, but I'm stuck on this. Can anyone point out my flaw(s)?

var internals = new Mock<DbSet<InternalTransaction>>();
var theData = new List<InternalTransaction>().AsQueryable();

internals.As<IQueryable<InternalTransaction>>().Setup(m => m.Provider).Returns(theData.Provider);
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.Expression).Returns(theData.Expression);
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.ElementType).Returns(theData.ElementType);
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.GetEnumerator()).Returns(theData.GetEnumerator());

var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
mockDC.Setup(q => q.InternalTransactions.Create()).Returns(new InternalTransaction());
mockDC.Setup(q => q.InternalTransactions.Add(It.IsAny<InternalTransaction>()));

var it = mockDC.Object.InternalTransactions.Create();
it.Id = "123";
mockDC.Object.InternalTransactions.Add(it);

internals.Verify(e => e.Add(It.Is<InternalTransaction>(d => d.Id == "123")), Times.Once());
//or:  Assert.Equal(1, mockDC.Object.InternalTransactions.Count());

This test fails with: Expected invocation on the mock once, but was 0 times: e => e.Add(It.Is(d => d.Id == "123")) No setups configured. No invocations performed.

The Assert statement, if used instead, fails with a NotImplementedException: "The member IQueryable.Provider has not been implemented on type DbSet~1Proxy_1 which inherits from DbSet1. Test doubles for DbSet1 must provide implementations of methods and properties that are used."

share|improve this question
1  
Does the verify pass with It.IsAny<InternalTransaction>()? If so, check the type of Id. If not, maybe you need to Setup the Add method on your internals mock rather than mockDC. –  Adam47 Jul 7 at 15:09
    
It does not pass--I get a slightly different error of "expected invocation on the mock at least once, but was never performed". I replaced the line "mockDC.Setup(q => q.InternalTransactions.Add(It.IsAny<InternalTransaction>()));" with "internals.Setup(q => q.Add(It.IsAny<InternalTransaction>()));" - same result –  James in Indy Jul 7 at 15:57
    
One thing - if InternalTransactions is a property, you'll need to use SetupGet. And as per Adam, I believe the Create and Add setups may need to be done on internals, not on mockDC. –  StuartLC Jul 7 at 15:58
    
SetupGet on the mockDC or on internals? –  James in Indy Jul 7 at 16:26
    
Wait... this seems to have done something. I changed the Setup of Create() from mockDC to internals and the test passes! I need to investigate further to see if this is truly working, but I think we're on the right track. –  James in Indy Jul 7 at 16:34

1 Answer 1

up vote 0 down vote accepted

After comments by Adam and Stuart plus further experimentation, I was able to reduce my test case to the following working test case:

var internals = new Mock<DbSet<InternalTransaction>>();
var mockDC = new Mock<IDataContext>();

mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
internals.Setup(q => q.Create()).Returns(new InternalTransaction());

var transaction = new ExternalTransaction { [set criteria for Condition A] };

SomeBusinessObject.AddTriggeredInternalTransactions(mockDC.Object, transaction);

// verify the Add method was executed exactly once
internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.