Unit testing with Moq, Prism 6, and Event Aggregation - unit-testing

I want to unit test a module by throwing messages at it via Event Aggregation to make sure it responds appropriately, either by setting properties appropriately, or by publishing other messages as a result. I am using Prism 6.
In my project, the infrastructure project has:
public class ImportantMessage : PubSubEvent<string>
{
}
ModuleA publishes a message like this:
eventAggregator.GetEvent<ImportantMessage>().Publish(importantString);
ModuleB receives the message like this:
eventAggregator.GetEvent<ImportantMessage>().Subscribe(HandleImportantMessage);
Here is HandleImportantMessage:
public void HandleImportantMessage(string importantString)
{
. . .
}
The ModuleB constructor is called as follows:
ModuleB(IEventAggregator EventAggregator)
This constructor is called by the Prism framework. For unit testing, I need to create an instance of ModuleB, and pass an IEventAggregator, probably a fake one created by Moq. And I want to do this in such a way that the message I publish carries importantString with it.
If I Google the phrase “unit tests with moq and event aggregation,” there are
several references, but I didn’t see how to use any of these approaches to pass “importantString” from ModuleA To ModuleB. The sample code for Prism 5 creates a fake event aggregator, but without using Moq. I don't understand how it works, and don't see how to pass a string with it.
My test code starts off something like this:
var moqEventAggregator = new Mock(IEventAggregator);
var moqImportantMessage = new Mock<ImportantMessage>();
moqEventAggregator.Setup(x => x.GetEvent<ImportantMessage>());
Some of the references I have seen apply something like .Returns(eventBeingListenedTo.Object);
to moqEventAggregator after Setup is applied.
I obviously need to apply .Setup(something) to moqImportantMessage in order to pass importantString, but I don't see exactly what yet.
What am I missing? How do I pass a string with the fake published message?

Basically you need to mock 2 things here:
The event aggregator
The event itself
Given you have the mock of the event you need to do as you said:
moqEventAggregator.Setup(x => x.GetEvent<ImportantMessage>()).Returns(moqImportantMessage);
Mocking the event itself should be like so:
Action<string> action;
moqImportantMessage.Setup(_ => _.Subscribe(It.IsAny<Action<string>>>()))
.Callback(_action =>
{
action = _action;
});
And then you can raise the subscription like so:
action("some string");

Related

trouble debugging async Task in unit test because it's not entered

So I am trying to test a method of type async Task that is called inside of a command handler, inside that method I have some ifs and I want to check on which branch it goes.
Because on each branch a certain method is called, I can see which branch it went to by
await myRepository.Received(1).Method1(3, null);
Imagine the key method is like this:
public async Task MyKeyMethod(int x) {
if (x == 21)
Method1("bla");
if (x == 22)
Method2("blue");
if (x == 23)
Method3("ba");
}
So I want to test that the call MyKeyMethod(2) actually goes into the branch that calls Method2("blue");
And I know that I can do this by something like:
await MyKeyMethod.Received(1).Method2(22); // Received(1) means that method was invoked once.
Question 1: what should 22 be? The parameter supplied to Method2 or the one supplied to MyKeyMethod?
Question2: Why does my code not even enter any async Task method that I have inside the command handler (during debugging)?
Is there any concrete example that you have?
I am able to enter step by step the command by doing something like:
var cmd = new MyCommand(myObject); // myObject is an object that I mocked earlier (gave it some dummy values for each field)
var commandResponse = await handler.Handle(cmd);
Assert.That(commandResponse.IsSuccessful, Is.True);
...just NOT at the next deeper level, like the async Tasks inside those commands. I can just at the moment simulate what the async Task return, which is not what I want in this instance.
Question 3. Could this be because those async Task methods are inside a repository that is mocked by using
myRepository = Substitute.For<IMyRepository>();
Question 4. How do I enter actually not mockingly Task methods found inside Repositories that are mocked?
I am still getting the hang of it, "it" being the broader subject of unit tests in NUnit, but apparently my hunch was right. Because the repository was mocked, I could not enter and debug inside of one of its contained methods. So I used a real (not fake) method of the repository which by the way took in its constructors some fake instances of other dependant repos or services, and then I could go inside that Task.
So, factually, instead of:
myRepository = Substitute.For<IMyRepository>();
I went and created a real instance, such as:
var myRepository = new MyRepository>(mockService1, mockRepo2);
where mockService1 was mocked using Substitute like previously pointed out.
And by doing so I could then debug a method like:
myRepository.MyMethod(x) which previously the debugger couldn't analyse the inside of.
If you have a better way of phrasing my conclusions, by all means, or more complete explanation, please go ahead. Thank you

How to unit test Service Fabric Actor with State

I've started writing unit tests for new actor with state. The state is initialised in the OnActivateAsync method which is called by Service Fabric when the Actor is activated.
When unit testing, I'm creating the Actor myself and as the method is protected I don't have access from my unit test to call this method myself.
I'm wondering on the usual approach for this kind of testing. I could mock the Actor and mock the state, but for the code I want to test call the original. Am wondering if there is another approach I've not come across.
Another approach would be to move the State initialisation to somewhere else like a public method or in the constructor but the template for an Actor has the code there so it may be a best practice.
Use the latest version of ServiceFabric.Mocks NuGet package. It contains special extension to invoke OnActivateAsync protected method and the whole tool set for ServiceFabric unit testing.
var svc = MockActorServiceFactory.CreateActorServiceForActor<MyActor>();
var actor = svc.Activate(new ActorId(Guid.NewGuid()));
actor.InvokeOnActivateAsync().Wait();
I like to use the InternalsVisibleTo attribute and an internal method on the actor, which calls the OnActivateAsync method.
In the target Actor project, AssemblyInfo.cs add a line like this:
[assembly: InternalsVisibleTo("MyActor.Test")]
Where "MyActor.Test" is the name of the test project you want to grant access to your internal members.
In the target Actor class add a method something like this:
internal Task InvokeOnActivateAsync()
{
return OnActivateAsync();
}
This way you can invoke the OnActivateAsync method from your test project something like this:
var actor = CreateNewActor(id);
actor.InvokeOnActivateAsync()
I appreciate this is not ideal, but you can use reflection to call the OnActivateAsync() method.
For example,
var method = typeof(ActorBase).GetMethod("OnActivateAsync", BindingFlags.Instance | BindingFlags.NonPublic);
await (Task)method.Invoke(actor, null);
This way you'll be testing the actual method you want to test and also won't be exposing methods you don't really want to expose.
You may find it useful to group the creation of the actor and the manual call to OnActivateAsync() in a single method so that it's used across your test suite and it mimics the original Service Fabric behaviour.

Mocking an object with Moq, using Ninject when doing UnitTesting

I'm having trouble using Moq in a UnitTesting project with Ninject.
First a few lines about my solution. It contains several projects (BussinesLogic, DAL, Infrastructure...). My goal is to UnitTest the logic i'm using in BussinessLogic project.
The solution is basicly for a windows service, but i've put in the logic so it can be run standalone. I'm using Ninject and i specify weather i want to use the ProductionModule or the TestingModule (windows service uses ProductionModule, console app uses TestingModule)
I'm using a factory pattern to get ninject kernel whenever i need it inside my application.
My TestingModule inherits from NinjectModule where i override the Load() method and there i do the binding. For instance:
Bind<IStorageManager>().To<StubStorageManager>();
I have the StubStorageManager but it's empty. It contains just the declaration of methods from IStorageManager.
The thing i would like to do is (in laymans terms):
Create a unitTest where i would create a new kernel specifying the TestingModule as it's parameter. Then i would like to create a mock object (let's say a mock of IStorageManager) storageManagerMock. Some method in IStorageManager returns a messageObject so i would probably need to mock that too, couse the bussiness logic is doing something based on that messageObject. So i would like to somehow set properties to that message object and then call some businessLogic method on it, so i can see if the logic works correctly.
I hope i didn't complicate it too much.
Please bear with me, i'm completely new to mocking and dependency injection, but am willing to learn.
I doubt you really want to be using Ninject in your tests. The whole point of using ninject is that you can decouple everything. You also want to try and keep everything decoupled from the dependency container itself if possible. Pass it in if you have to, or pass in factories that create the required object and have the container pass in the factory.
I suspect you probably want to do something like this:
public void ATest(){
//create a mock StorageManager
var managerMock = new Mock<IStorageManager>();
//create a mock MessageObject to be used by business logic
var messageObjectMock = new Mock<MessageObject>();
//have the storage manager return the mock message when required
managerMock.Setup(x => x.GetMessageObject()).Returns(messageObjectMock.Object);
//set up message expectations
messageObjectMock.Setup(x => x.ThisValueExpected).Returns(10);
messageObjectMock.Setup(x => x.ThisFunctionShouldBeCalled()).Verifiable("Function not called.");
//thing to test
BusinessLogicObject blo = new BusinessLogicObject(managerMock.Object);
blo.DoTheThingImTesting();
//make sure the business logic called the expected function, or do whatever check you need...
messageObjectMock.Verify();
}

ASP.NET MVC2 Custom View Engine ignored in unit tests

I'm trying to unit test a controller that stuffs data into a ViewData. All our views require similar data (Customer info which is derived from the url). So instead of putting the call into every single controller method, the original developers chose to put this ViewData stuffing into the OnActionExecuting event.
Of course, when you invoke the controller's action from a unit test, OnActionExecuting doesn't fire. (Thanks MVC Team!)
So I tried creating a custom view engine and having it stuff the customer data into the controllerContext when the view is requested. This works fine in a browser, but my viewEngine is ignored when I run this test. No amount of ViewEngines.Add(new funkyViewEngine) has any effect.
[TestMethod()]
public void LoginTest()
{
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new FunkyViewEngine());
UserController target = new UserController();
target.SetStructureMap(); <--sets us to use the test repo
target.ControllerContext.HttpContext = MVCHelpers.FakeHttpContext("https://customersubdomain.ourdomain.com"); <--moq magic
var actual = target.Login();
Assert.IsTrue(actual.GetType().IsAssignableFrom(typeof(System.Web.Mvc.ViewResult)));
var vr = actual as ViewResult;
Assert.IsTrue(vr.ViewData.Community() != null); <--"Community" should be set by viewengine
Assert.IsTrue(vr.ViewData.Community().Subdomain == "customersubdomain.ourdomain");
Assert.IsTrue(vr.ViewData.Community().CanRegister);
}
Is there any hope here? How do I either 1) create a method that gets called on controller execution BOTH in the browser and the unit framework or 2) get the unit framework to invoke my view engine.
Sorry for your frustration. The reason why you are seeing OnActionExecuting not being called when you directly call your action method from the unit test is because that's not how things work in MVC.
The request gets executed via a "pipeline", which as far as this area is concerned consists of the ControllerActionInvoker. This class is responsible for:
Finding the action method
Invoking action filters' OnActionExecuting method (note: your controller class is also an action filter)
Calling the action method itself
Invoking the action filters' OnActionExecuted method
Handling the result (e.g. finding the view and rendering it)
In your unit test you are directly invoking step 3. and skipping all the other steps. In a unit test, it is your responsibility to call any setup code required for your action to work.
However, this does not mean you should now write unit tests that use the ControllerActionInvoker to execute the entire pipeline. We (the MVC team) have already verified that all the pieces work together.
Instead, you should test your specific application code. In this case, you might consider having the following unit tests:
A test that verifies that given some Url calling OnActionExecuting on your controller puts the right Customer object into ViewData
A test that verifies that given some Customer object present in ViewData your action method returns the appropriate result
My last point is that you should keep the functionality in OnActionExecuting. A custom view engine is definetely the wrong place for it.
Not an answer you're probably looking for, but I'm using a custom MvcHandler to achieve the same goal (getting customer from URL in multi-tenant app). ViewEngine doesn't sound like a good place for this kind of logic to me...
My custom handler looks more or less like this:
public class AccountMvcHandler : MvcHandler
{
public Account Account { get; private set; }
protected override IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
{
return base.BeginProcessRequest(httpContext, callback, state);
}
protected override IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
{
string accountName = this.RequestContext.RouteData.GetRequiredString("account");
Account = ServiceFactory.GetService<ISecurityService>().GetAccount(accountName);
return base.BeginProcessRequest(httpContext, callback, state);
}
}

Using Moq callbacks correctly according to AAA

I've created a unit test that tests interactions on my ViewModel class in a Silverlight application. To be able to do this test, I'm mocking the service interface, injected to the ViewModel. I'm using Moq framework to do the mocking.
to be able to verify bounded object in the ViewModel is converted properly, I've used a callback:
[Test]
public void SaveProposal_Will_Map_Proposal_To_WebService_Parameter()
{
var vm = CreateNewCampaignViewModel();
var proposal = CreateNewProposal(1, "New Proposal");
Services.Setup(x => x.SaveProposalAsync(It.IsAny<saveProposalParam>())).Callback((saveProposalParam p) =>
{
Assert.That(p.plainProposal, Is.Not.Null);
Assert.That(p.plainProposal.POrderItem.orderItemId, Is.EqualTo(1));
Assert.That(p.plainProposal.POrderItem.orderName, Is.EqualTo("New Proposal"));
});
proposal.State = ObjectStates.Added;
vm.CurrentProposal = proposal;
vm.Save();
}
It is working fine, but if you've noticed, using this mechanism the Assert and Act part of the unit test have switched their parts (Assert comes before Acting). Is there a better way to do this, while preserving correct AAA order?
I'm not sure that you've changed the semantics of the AAA order. Consider the execution of the test. Your mocked interface will not be called until the Action invokes it. Therefore, during execution, your program still follows the Arrange, Act, and Assert flow.
The alternative would be to use Data Injection and create an interface between your CampaignViewModel and the web service that it uses. You can then create a class in your UnitTests that saves your parameter information and Assert on that class member/property rather than use Moq to create a proxy on the fly.
Moq should not be used to simulate storage or assignment. Rather, use Moq to provide dummy mechanisms and values to allow your Unit Tests to execute. If Asserting storage is a requirement, then take the time to create a class that will hold on to your values.