Error when using Machine.Specs to test class using MVC MailerBase - c#

I'm receiving an error when I try to test a class (FindTask) that is making a call to another class (NotificationMailer) that inherits from MVC MailerBase.
System.ArgumentNullException: Value cannot be null.
Parameter name: httpContext
class FindTask
{
public void Find()
{
notificationMailer.Notify("Some message").Send();
}
}
I'm trying to verify that FindTask calls NotificationMailer::Notify.
public class NotificationMailer : MailerBase, INotificationMailer
{
public NotificationMailer()
{
MasterName = "_Layout";
}
public virtual MvcMailMessage Notify(string message)
{
return Populate(x =>
{
x.Subject = "Some Notification";
x.ViewName = "Notify";
x.To.Add("testEmail#test.com");
x.Body = message;
});
}
}
The error is on the return Populate(...) line.
public class FindTaskSpec : WithSubject<FindTask>
{
Establish context = () =>
{
MvcMailMessage mailMessage = new MvcMailMessage();
The<INotificationMailer>()
.WhenToldTo(x => x.Notify(Param<string>.IsAnything))
.Return(mailMessage);
};
Because of = () => Subject.Find();
}
public class when_something_is_found : FindTaskSpec
{
It should_send_an_email_with_the_found_stuff = () => The<IDeadLinkMailer>()
.WasToldTo(x => x.Notify(Param<string>.IsAnything))
.OnlyOnce();
}
I think the line in Establish context(the mock) should dictate that if Notify is called, it should return a new MVCMailMessage without running through the body of the function.
My Questions:
How can I resolve this error and test to make sure the Notify method is called?
Why is it that the mock for Notify does not stop the test from entering the function body of notify?
On a side note I've already tried setting MailerBase.IsTestModeEnabled = true. This results in an Url error - Invalid Url: The Url is Empty;
I've read through their wiki page on setting up tests for MvcMailer.
I've also read almost all the other stack overflow pages on this. I think that this link was most helpful. The problem is that I don't know how to imitate what they do in this link with Machine.Specifications.
I think my issue would be resolved if I could create a mock for either of the methods shown in the links.

I think in this situation I would be tempted to just create a FakeNotificationMailer class, by deriving from NotificationMailer and overriding the Notify method and having it return a pre-built MvcMailMessage. That's essentially the same as what your mock is doing, but everything is explicit. Something like:
public class FakeNotificationMailer : MailerBase, INotificationMailer
{
MvcMailMessage preBuiltMessage;
public NotificationMailer(MvcMailMessage result)
{
preBuiltMessage = result;
}
public virtual MvcMailMessage Notify(string message)
{
return preBuiltMessage;
}
}
(I had problems figuring out what your dependencies are, so that's a bit of a shot in the dark).
Of course then you have to find somewhere that you can inject your fake implementation (Dependency Inversion Principle).

Related

How can I assure my domain entity's method was called before other method?

I want to write a test that assures that a method of my domain entity was called before the repository method, so I can guarantee the information was changed before being persisted.
So in my sample domain service implementation, I inverted the orders of the calls, so I could see the test failing.
using NSubstitute;
using Xunit;
namespace MyProject
{
public interface IMyService
{
void MyServiceMethod(MyEntity entity);
}
public interface IMyRepository
{
void Persist(MyEntity entity);
}
public class MyEntity
{
public string MyProp { get; private set; }
public void ChangeMyProp(string newValue)
{
MyProp = newValue;
}
}
public class MyService : IMyService
{
private readonly IMyRepository _myRepository;
public MyService(IMyRepository repository)
{
_myRepository = repository;
}
public void MyServiceMethod(MyEntity entity)
{
_myRepository.Persist(entity); // this is a wrong fake implementation that should me caught on test
entity.ChangeMyProp("I am changing you");
}
}
public class MyServiceTest
{
[Fact]
public void MyServiceMethod_Should_ChangeProp_Before_Persists()
{
var repository = Substitute.For<IMyRepository>();
var service = new MyService(repository);
var myEntity = new MyEntity();
service.MyServiceMethod(myEntity);
Received.InOrder(() =>
{
myEntity.ChangeMyProp("I am changing you");
repository.Persist(myEntity);
});
}
}
}
The problem is that this tests is passing. The only thing I can think about is writing an interface for my MyEntity or make that method virtual, so maybe nsubstitute can deal with that, but that sounds not good for me because this is my domain entity and nobody outside domain should make implementations or override this logic.
Any way I can test this calls order?
PS: If you only know how to that with Moq or other Mock library, it's not a problem. It will help me as well. I can change it.
Edit
I also tried the following code and it didn't work. This also passed.
repository.Received().Persist(Arg.Is<MyEntity>(e => e.MyProp == "I am changing you"));
Edit 2
I found a related issue on github that helped me to solve the problem and I posted an answer. Although I don't like that solution since is not very clean for me, but it's okay, it's all I have for now.
You could just verify what the Persist method is receiving. If the received entity has the changed value, you know the order was correct.
Verifying a method call to an object that cannot be mocked is always difficult and usually points to a design issue.
I found a solution here.
[Fact]
public void MyServiceMethod_Should_ChangeProp_Before_Persists()
{
var repository = Substitute.For<IMyRepository>();
var service = new MyService(repository);
var myEntity = new MyEntity();
var namePersisted = string.Empty;
repository.Persist(Arg.Do<MyEntity>(e => namePersisted = e.MyProp));
service.MyServiceMethod(myEntity);
Assert.Equal(myEntity.MyProp, namePersisted);
}

AutMocker with Setup not working properly

I am trying to use Moq.Automock in one of my projects, which I have not used before. Please see the code below:
[TestFixture]
public class BusinessLayerTests
{
List<Denomination> expectedDenominations;
AutoMocker mocker = new AutoMocker();
UKCurrency Currency;
IDenominationFactory DenominationFactory;
[OneTimeSetUp]
public void Initialize()
{
Currency = mocker.CreateInstance<UKCurrency>();
DenominationFactory = mocker.CreateInstance<DenominationFactory>();
mocker.Setup<UKCurrency>(x => x.CurrencyDenominations()).Returns(CurrencyDenominations());
}
public System.Collections.Generic.IEnumerable<decimal> CurrencyDenominations()
{
yield return 50M;
}
}
I believe the code above shows that I have created a mock object called: Currency. I believe the line starting: mocker.Setup should ensure that the local method called: CurrencyDenominations is called. However, this does not happen. The method called: CurrencyDenominations in UKCurrency is called.
What am I doing wrong?
You need to get the underlying mock and apply the setup on that.
[OneTimeSetUp]
public void Initialize() {
Currency = mocker.CreateInstance<UKCurrency>();
DenominationFactory = mocker.CreateInstance<DenominationFactory>();
var currencyMock = mocker.GetMock<UKCurrency>();
currencyMock.Setup(_ => _.CurrencyDenominations()).Returns(CurrencyDenominations());
}
provided UKCurrency.CurrencyDenominations is virtual and able to be overridden.

Akka.net deadlocking issue with ActorSelection

Having an issue with akka.net. I need to access an actor which I have already created with a specific name. I can retrieve the actor from IActorContext but I am struggling to access it from the ActorSystem.
I have created a method called GetOrCreateActor which attempts to get the actor using ActorSelection. If it doesn't exist, the catch creates a new actor with the name. If it does exist, I want it to return the reference. However, it never returns from '.Result'. Assuming this could be some sort of deadlocking issue.
public static IActorRef GetOrCreateActor<T>(this ActorSystem actorSystem, string actorPath, string name = null) where T : ActorBase
{
try
{
return actorSystem.ActorSelection(actorPath).ResolveOne(TimeSpan.FromSeconds(1)).Result;
}
catch
{
return actorSystem.ActorOf(actorSystem.DI().Props<T>(), name);
}
}
Edit
I've tried to include a simplified version of the calling code below.
The actor system is created in an IOC container using AutoFac (ExampleActor is the ReceiveActor I am trying to access):
containerBuilder.RegisterAssemblyTypes(typeof(ExampleActor).Assembly).Where(x => x.Name.EndsWith("Actor"));
var lazyContainer = new Lazy<IContainer>(() => containerBuilder.Build());
containerBuilder.Register(c =>
{
var system = ActorSystem.Create("ExampleActorSystem");
new AutoFacDependencyResolver(lazyContainer.Value, system);
return system;
}).As<ActorSystem>().SingleInstance();
return lazyContainer.Value;
ActorSystem is then injected into another class, where I call the GetOrCreateActor method (via the Execute method):
public class ExampleCommand : IExampleCommand
{
private readonly ActorSystem _actorSystem;
public ExampleCommand(ActorSystem actorSystem)
{
_actorSystem = actorSystem;
}
public void Execute()
{
SendMessage();
}
private void SendMessage()
{
string message = new Message();
_actorSystem.GetOrCreateActor<ExampleActor>("akka://ExampleActorSystem/user/ExampleActor", "ExampleActor").Tell(message);
}
}
The above command would be called from a RESTful endpoint
public ExampleGetModule(IExampleCommand exampleCommand)
{
Get["/api/createExample"] = parameters =>
{
exampleCommand.Execute();
};
}
Your deadlocking issue looks more like it has to do with how you're using your container than it does Akka.NET:
var lazyContainer = new Lazy<IContainer>(() => containerBuilder.Build());
containerBuilder.Register(c =>
{
var system = ActorSystem.Create("ExampleActorSystem");
new AutoFacDependencyResolver(lazyContainer.Value, system);
return system;
}).As<ActorSystem>().SingleInstance();
In terms of what can go wrong here, self-referential Lazy<T> types are an infamous source of race-conditions. You should not be calling lazyContainer.Value inside of this registration method if the output of containerBuilder.Build depends on the input of containerBuilder.Register.
Last thing is to use step-through debugging to make sure that your application actually calls into the ResolveOne method here - if you're not getting a timeout exception back then it means that your application is deadlocking on producing the actor system (because of how DI is configured).

Moq Method called by System.Threading.Tasks.Task.Factory.StartNew

I am using Moq to write a unit test. I have a DataManager object which calls WCF to fetch data. I inject this into my controller. however inside the controller the call to the Method in this DataManager is wrapped inside of a Task
System.Threading.Tasks.Task.Factory.StartNew<MyDataObject>(()=>
{
return DataManager.GetMyDataObject(userobj, recordid);
}
I have created a mock for the DataManager.GetMyDataObject with Moq
but whenever it is called from this statement inside of the controller method
it returns null. I have googled alot but most of the stuff out there are dealing with methods which have Task as the return signature.
The DataManager.GetMyDataObject is written as standard sync code.
I am using Moq v4.0.10827 and doubt I can upgrade.
I am trying many ways..Moq seems to expect the return to match the method signature
_mockDataManager = new Mock<_mockDataManager>();
_mockDataManager.Setup(m => m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>()))
and well then returns? I also trid callback
_mockDataManager.Setup(m => System.Threading.Tasks.Task.FromResult(m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>())
.Returns(System.Threading.Tasks.Task.FromResult(myData))
.Callback<MyDataObject>(o => myData = o);
myData = GetMyDataObject();
_mockDataManager.Setup(m => m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>()).Returns(GetMyDataObject())
private GetMyDataObject() {
returns new DataSet(); //basically an empty dataset but not null
}
Given the following classes:
public class MyDataObject { }
public class UserObj { }
public class DataManager
{
public virtual MyDataObject GetMyDataObject(UserObj userObj, Guid guid)
{
throw new NotImplementedException();
}
}
class SUT
{
public DataManager DataManager { get; private set; }
public SUT(DataManager dataManager)
{
DataManager = dataManager;
}
public void Method(UserObj userobj, Guid recordid)
{
var t = System.Threading.Tasks.Task.Factory.StartNew<MyDataObject>(()=>
{
return DataManager.GetMyDataObject(userobj, recordid);
});
t.Wait();
}
}
the following mock works fine:
var mockDataManager = new Mock<DataManager>();
mockDataManager.Setup(m => m.GetMyDataObject(It.IsAny<UserObj>(), It.IsAny<Guid>()));
var sut = new SUT(mockDataManager.Object);
sut.Method(new UserObj(), Guid.Empty);
mockDataManager.VerifyAll();
Two pitfalls:
In the code you posted, you use
_mockDataManager = new Mock<_mockDataManager>();
which should be
_mockDataManager = new Mock<DataManager>(); // or whatever the name of the class is
Maybe this is just a copy/paste error, maybe not.
Also, since you use a Task here:
System.Threading.Tasks.Task.Factory.StartNew<MyDataObject>(()=>
{
return DataManager.GetMyDataObject(userobj, recordid);
}
which calls GetMyDataObject on DataManager, you have to make sure that the Task finished before you verify your mock setup. If you would remove the t.Wait(); from my code above, the test would fail, because VerifyAll would be called before the Task would start and call GetMyDataObject in the mocked object.

Managing services fed into MVC controllers by AutoFixture in a generic test helper

I'm new to AutoFixture and am trying to create a friendly extension on my test context for the less TDD-inclined devs in the team. Here is the code:
public class HomeController : Controller
{
private readonly ISomeService _someService;
public HomeController(ISomeService someService)
{
_someService = someService;
}
public ActionResult Index()
{
_someService.SomeMethod();
return View("Index");
}
}
public class ControllerContext<T> where T : Controller
{
protected static T ControllerUnderTest;
private static IFixture _fixture;
public ControllerContext()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_fixture.Customize<ControllerContext>(c => c.Without(x => x.DisplayMode));
ControllerUnderTest = _fixture.Create<T>();
}
protected static Mock<TDouble> For<TDouble>() where TDouble : class
{
//var mock = _fixture.Create<TDouble>();
var mock = _fixture.Create<Mock<TDouble>>();
return mock;
}
}
So the extension is the For method - When I inspect ControllerUnderTest which has an injected 'ISomeService' it has an instance injected just fine, and it definitely calls the method I am asserting against. When I inspect the mock created in the 'For' method it appears to be the same version as the one injected to the controller, but it won't Verify!
public class EXAMPLE_When_going_to_home_page : ControllerContext<HomeController>
{
Because of = () =>
{
ControllerUnderTest.Index();
};
It should_do_something = () =>
{
//This throws a 'Invocation was not performed'
For<ISomeService>().Verify(x => x.SomeMethod());
};
Establish context = () =>
{
};
}
I am struggling to find any examples of someone doing something similar, I know I am definitely doing something stupid here but in my head this test should pass?
Create creates a new anonymous instance every time, unless you froze (via .Freeze<T>() or AutoFixture.Xunit's [Frozen]) an instance. That means that the value that is injected into HomeController is different from the one returned by For.
There are several possible solutions, all of which ultimately will involve Freezing the value or Injecting the one to use.
One example would look like this:
public class ControllerContext<T> where T : Controller
{
private static Lazy<T> _controllerFactory;
private static IFixture _fixture;
public ControllerContext()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_fixture.Customize<ControllerContext>(c => c.Without(x => x.DisplayMode));
_controllerFactory = new Lazy<T>(() => _fixture.Create<T>());
}
protected static Mock<TDouble> For<TDouble>() where TDouble : class
{
var mock = _fixture.Freeze<Mock<TDouble>>();
return mock;
}
protected static T ControllerUnderTest
{
get { return _controllerFactory.Value; }
}
}
public class EXAMPLE_When_going_to_home_page : ControllerContext<HomeController>
{
static Mock<ISomeService> SomeService;
Because of = () =>
{
SomeService = For<ISomeService>();
ControllerUnderTest.Index();
};
It should_do_something = () =>
{
//This throws a 'Invocation was not performed'
SomeService.Verify(x => x.SomeMethod());
};
Establish context = () =>
{
};
}
The important point of this changed version is that first Freeze is called on the service mock and only after that the anonymous instance of the controller is created. Because of the way the For method is now used, you should probably rename it to GetService.
You'll ultimately end up in a world of pain if you go down the road of having static state as a way of managing the interaction between the services and the SUT. One reason is for example that unit tests should be parallelizable (e.g. xUnit.net v2 but ultimately all test frameworks as it just makes sense)
You can add Customizations to AutoFixture to allow natural creation of MVC Controllers as needed and then it's just a matter of feeding in or Freezing customized dependencies as necessary.
I'd strongly suggest taking the time to change your structure of your tests to have AutoFixture creating the Controller declaratively - have a look at what's possible with AutoFixture.Xunit and use that to inform how you structure the test helpers you're using in your Specs.
(Some background - I've been around the houses with all this Spec stuff using SubSpec and ultimately ended up much happier with AutoFixture.Xunit - it's just simpler and more composable.

Categories