Reputation: 6458
I've recently added a new method to my repository as I need to process my database calls in transaction mode and all is working well but now that I'm trying to adjust the unit tests, I'm having a problem.
My new void method (i.e. InTransaction), accepts an Action
as a parameter where I can just pass a anonymous method to it:
myFunction()
{
MyObject data1 = null;
MyObject data2 = null;
UnitOfWork.InTransaction(() =>
{
data1 = DoSomething(a,b,c);
data2 = DoSomething(a,b,c);
UnitOfWork.Save();
});
var isValidData1 = IsValid(data1);
var isValidData2 = IsValid(data2);
}
The problem I'm facing is that I still need data1 and data2 to be set to some value or my IsValid function will bomb out as it does not accept null (simplified explanation btw!).
DoSomething is a private method, it still calls other public functions/methods that are also mocked.
if I call the above code
My DoSomething method are private but they are making calls without this new InTransaction method:
myFunction()
{
MyObject data1 = null;
MyObject data2 = null;
data1 = DoSomething(a,b,c);
data2 = DoSomething(a,b,c);
UnitOfWork.Save();
var isValidData1 = IsValid(data1);
var isValidData2 = IsValid(data2);
}
All my mocks work as expected and DoSomething will return data as expected and IsValid will also work as expected.
So moqqing my new InTransaction as:
unitOfWork.Setup(uow => uow.InTransaction(It.IsAny<Action>());
will moq correctly but the problem is that the rest of MyFunction
function will fail as IsValid
expects data1 and data2 to be set to something specific.
I've looked at Callback but I don't think it's suitable for this. I'm using it in other unit tests but these are used on function rather than a void method where I'm allowed to set parameters to various objects.
Any ideas how I can return data from a moq void method that takes in an Action parameter inside the function being tested.
Thanks.
Upvotes: 3
Views: 478
Reputation: 247088
The action will need to be invoked so that the code behaves as expected
A Callback
can be used to grab the passed action parameter. From there it can be invoked
unitOfWork
.Setup(_ => _.InTransaction(It.IsAny<Action>())
.Callback((Action action) => action()); //invoke the action within the callback
This will allow
//...
() => {
data1 = DoSomething(a,b,c);
data2 = DoSomething(a,b,c);
UnitOfWork.Save();
}
//...
to be run as it should when the test is exercised.
Upvotes: 4