I've been using FakeXrmEasy to write unit tests for the past week or so, and I'm generally happy with how it works. But there's one area where I'm not able to get the mock to work as I want it to.
In the Dynamics CRM installation, there's a plugin running, that sets the Order Number on the Sales Order. Without this, the returned order number's value is always null.
How can i tell the FakeXrmEasy mock to set the ordernumber value? Ideally I'd like to tap into the request pipeline more or less like so:
var context = new FakeXrmEasy.XrmFakedContext();
context.Initialize(TestEntities);
context.TamperWithResults<RetrieveRequest>( x => {
return SetOrderNumber(x);
});
context.GetFakedOrganizationService();
var result = context.Retrieve(...);
I could attempt using the .AddExecutionMock to mock the entire result, but the response in question is used to verify that the sales order was indeed saved with the correct values.
Update - more detailed info Perhaps I should have gone a little more into detail when asking the question. I've just joined an exisiting project and I'm writing tests to existing code. The failing test is running a function that does this:
Now since the function attempts to save the order, I cannot add it to the context in setup unless I can specify the Guid that will be returned by the Create() call.
Assuming you are writing a unit test for testing whatever happens after that plugin (the plugin which populates the Order Number), the easiest solution is to initialize a sales order with the OrderNumber in it, which will be used as the precondition. Queries are automatically mocked by default, so that value should be returned. No need to inject anything in the pipeline because of that.
Example:
[Fact]
public void Example_test()
{
var context = new XrmFakedContext();
var service = context.GetFakedOrganizationService();
var salesOrder = new SalesOrder() { Id = Guid.NewGuid(), OrderNumber = 69 };
context.Initialize(new List<Entity>() { salesOrder });
//some stuff
//....
//Queries are automatically mocked so any LINQ,FetchXml,
//QueryExpression or QueryByAttrubute should return the values you had in
//the context initialisation or as a result of updates / creates during the test execution
var result = context.CreateQuery<SalesOrder>().FirstOrDefault();
Assert.Equal(result.OrderNumber, 69);
}
[EDIT]: If you want to inject the guid after the Create you can use the OutputParameters property for that. Here's an example with the FollowupPlugin.
There are several overloads for plugin execution, that example used to be an "old" one. There is a new general purpose method where you can pass a custom plugin context, where you can inject many properties, including the Outputparameters (look for GetDefaultPluginContext here).
But in general, and back to your original question, if you have many steps like these:
There could be many approaches to unit test this stuff, but my personal advice is that, those steps are way too many steps to be included in a single unit test. I'd rather refactor that logic so that it could be unit tested separately, more easily.
I'll resume that to only 3 steps to make it simpler:
I would first, refactor that code so that I can test it much more easily, in small chunks. Doing this makes tests simpler to implement and understand & review.
I would create 3 different unit tests for each (at least!):
Hope this helps (now :P )!