chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
I’m trying to test a bit of code that is proving to be very difficult. I would appreciate any feedback, insight, or help. Here is a simplified version of the code under test:

public class RepositoryBase<T> : RepositoryBase where T : DataContext, new()
{
    protected static void Execute(Action<T> invocation)
    {
        using (var context = new T())
        {
            invocation(context);
        }
    }
}


public class FooRepository : RepositoryBase<FooDataContext>
{
    public virtual Guid CreateFoo(string name, string description, IEnumerable<Guid> foosThingIds)
    {
        var id = default(Guid?);

        // Call static, protected method inherited from RepositoryBase<T>.       
        Execute(delegate(FooDataContext context)
        {
            // THIS IS THE CODE I WANT TO TEST

            context.CreateFoo(name, description, ref id);

            // Use id and fooThingIds to make another call to the DB and other stuff
        }

        return id.Value;
    }
}


Because I don't want to test the base repository, in my unit test, I'm creating a reflective mock of type RepositoryBase<FooDataContext>, so that I can replace the protected, static Execute method and call the Action<T> object given to it. I have this working. However, the FooDataContext object passed to this action isn't the fake one that I create in my unit test.

This is the test that I'm currently stuck on:

[Test, VerifyMocks]
public void ShouldCreateFoo()
{
    Guid? expectedId = Guid.NewGuid();
    const string name = "foo", description = "baz";
    var dataContext = RecorderManager.CreateMockedObject<FooDataContext>();

    using (var recorder = RecorderManager.StartRecording())
    {
        recorder.ExpectAndReturn(dataContext.CreateFoo(name, description, ref expectedId), 0);
    }

    var baseRepositoryMock = MockManager.MockObject<RepositoryBase<FooDataContext>>();

    baseRepositoryMock.ExpectAndReturn("Execute", new DynamicReturnValue((parameters, context) =>
    {
        var action = parameters[0] as Action<FooDataContext>;

        Assert.IsNotNull(action);
        action(dataContext);

        return null;
    }));

    var repository = new FooRepository();
    var actualId = repository.CreateFoo(name, description, new List<Guid> { Guid.NewGuid() });

    Assert.That(actualId, Is.EqualTo(expectedId));
}


If this isn't clear or if you need more details/info to help, please let me know.

TIA!

--

Regards,

Travis Spencer
asked by travislspencer (1.3k points)

2 Answers

0 votes
Hi Travis,

I am assuming you want to verify that FooDataContext.CreateFoo was called and returned an expected Guid through its ref parameter. I came up with the following test; please let me know if this is what you meant:

[TestMethod]
[VerifyMocks]
public void TestCreateFooAssignedExpectedGuid()
{
      Guid? emptyId = Guid.Empty;
      Guid? expectedId = Guid.NewGuid();
      using (RecordExpectations rec = RecorderManager.StartRecording())
       {
            // the next time an FDC will be created it will behave like this one
            FooDataContext foo = new FooDataContext();
            // we expect CreateFoo() to be called (arguments are not important to us)
            foo.CreateFoo("", "", ref emptyId);
            // when CreateFoo() is called make sure we assign the expected Guid to its out parameter
            rec.CheckArguments(Check.IsAny(), Check.IsAny(), new Assign(expectedId));
        }

            var repo = new FooRepository();
            var actualId = repo.CreateFoo("", "", new[] {Guid.NewGuid()});
            Assert.AreEqual(expectedId, actualId);
       }
}


Note that I had to use Natural Mocks as out new AAA API still doesn't support ref and out parameters. Once this is supported the above test should be more readable and easier to implement. This feature is planned for one of the upcoming version updates, and I will update you with the syntax for testing it using AAA then.

Thanks,
Doron
Typemock support
answered by doron (17.2k points)
0 votes
doron,

Thank you for the suggestion. I didn't know how to use the record expectation object to set the reference argument like that.

However, what about the need to call the action given to the Execute method? That was the reason for the use of the DynamicReturnValue object. When using the DataContext in there, it seems that the object that is passed to the closure is not a fake. (This can be seen when debugging because the auto-generated code in the DataContext is outlined in purple when stepping into it.)

BTW, this thread seems to be overlapping with this one: https://www.typemock.com/community/viewt ... =4246#4246. Check that too for more info.

--

Regards,

Travis Spencer
answered by travislspencer (1.3k points)
...