MVC Core 2.0 Unit Testing and Automapper - unit-testing

I am attempting to Unit Test a method that uses Automapper ProjectTo and I'm not sure how to register the mappings in MVC Core. I am using the built in unit testing.
The following is my unit test.
[TestClass]
public class BusinessGenderServiceTest
{
[ClassInitialize]
public static void Init(TestContext context)
{
}
[TestMethod]
public void GetTest()
{
var options = new DbContextOptionsBuilder<GotNextDbContext>()
.UseInMemoryDatabase(databaseName: "GetTest")
.Options;
using (var context = new GotNextDbContext(options))
{
context.GenderLanguage.Add(new GenderLanguage { Id = 1, Name = "Male", Language = 1 });
context.GenderLanguage.Add(new GenderLanguage { Id = 2, Name = "Female", Language = 1 });
context.GenderLanguage.Add(new GenderLanguage { Id = 3, Name = "Hombre", Language = 2 });
context.GenderLanguage.Add(new GenderLanguage { Id = 4, Name = "Hombre", Language = 2 });
context.SaveChanges();
}
using (var context = new GotNextDbContext(options))
{
var service = new GenderService(context);
var result = service.Get(1);
Assert.AreEqual(2, result.Count());
}
}
}
I am getting the following error when I run the test:
Message: Test method GotNext.Test.BusinessGenderServiceTest.GetTest threw exception:
System.InvalidOperationException: Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.

I was able to solve this problem by configuring and initializing automapper in the Init method of each test class.
For example
[ClassInitialize]
public static void Init(TestContext testContext)
{
var mappings = new MapperConfigurationExpression();
mappings.AddProfile<LocationProfile>();
mappings.AddProfile<CompanyProfile>();
Mapper.Initialize(mappings);
}

You can configure AutoMapper in class like this:
public static class AutoMapperConfig
{
public static IMapper Initialize()
{
return new MapperConfiguration((cfg =>
{
cfg.CreateMap<User, UserDto>();
})).CreateMapper();
}
}
And next use it in startup.cs ConfigureService method
services.AddSingleton(AutoMapperConfig.Initialize());

Create a class or classes that configure AutoMapper and instantiate (and call methods, if applicable) in the Startup class.

I got this same error ("System.InvalidOperationException: Mapper not initialized. Call Initialize with appropriate configuration. ...") when I inadvertently / mindlessly switched between AutoMapper's Instance API (which I did have configured) and AutoMapper's Static API (which I did NOT have configured).
Looking closely at the line of code flagged in the error message, I realized I used upper-case 'M' Mapper.Map() instead of my instance member lower-case 'm' mapper.Map().

Related

How to unit test a service call in xUnit and nSubstitute

I been trying to figure out how i can unit test service and so far have got nowhere.
I am using xUnit and NSubstitute (as advised by friends), below is the simple test that i want to run (which fails currently).
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
My rally service class makes a simple call to the db to get all Rally entites and returns those:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
Any guidance would be appreciated.
Since you use .NET Core, I assume you also use Entity Framework Core. While it was possible to mock most of the operations in the previous EF version, however the EF Core suggests to use in-memory database for unit testing. I.e. you don't need to mock RallyDbContext, hence NSubstitute is not needed for this particular test. You would need NSubstitute to mock the service when testing a controller or application using the service.
Below is your Test1 written using in-memory database.
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
A working test application with this unit test is in my GitHub for your reference. I used SQL Express in the actual app.
I don't think it is standard to have a unit test constructor with a parameter. The unit test runner will new up this class, and unless you are using something that will auto-inject that parameter I think the test will fail to run.
Here is a standard fixture layout:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
If you need a common setup between tests, you can use a parameterless constructor and do common initialisation there.
In terms of the specific class you are trying to test, you need to make sure your RallyDbContext is in a known state to repeatably and reliably test. You may want to look up answers specific to testing Entity Framework for more information.

Retrieve data from MockRepository?

I'm new to Unit Testing and I'm using Rhino Mock in ASP.NET MVC
I have created a main test class with this code :
[TestFixture]
public class PersistenceTest
{
[Test]
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
var mockDataSource = MockRepository.GenerateMock<IRepository<T>>();
mockDataSource.Add(entity);
var fromDb = mockDataSource.FindBy(entity.Id);
return fromDb;
}
}
and create a customer test class like this :
[TestFixture]
public class CustomerTests : PersistenceTest
{
[Test]
public void Can_Save_And_Load_Customer()
{
var customer = new Customer()
{
Id = 12,
Name = "Reza",
Family = "Pazooki",
Company = "Rozaneh",
Email = "ipazooki#gmail.com",
Mobile = "09352463668",
Fax = "021-44869059",
Tel = "021-44869059",
WebSite = "www.rozanehmedia.com"
};
var fromDb = SaveAndLoadEntity(customer);
fromDb.ShouldNotBeNull();
}
}
but when run the code, it says that return value from Database is NULL!!!
I don't know what is wrong with my code but I save and retrieve data from mock repository and it seems every thing is ok.
tnx form any help in forward :)
Mocks are used to record invocations on objects for further verification or to provide values when called (later behavior requires setup).
In your SaveAndLoadEntity method you make calls to mock (Add and FindBy). Since mock is a fake object with no real behavior, those calls do nothing (they don't save nor extract any entities to/from database).
If you want to test persistence layer you should be doing tests against real database instance (or optionally, in-memory one).
// [Test] attribute is not needed
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
var dataSource = new DataSource("connection string");
dataSource.Add(entity);
var fromDb = dataSource.FindBy(entity.Id);
return fromDb;
}
At the moment you are making calls to not-setup mock which doesn't achieve anything.
Thank you jimmy_keen.
I change my code according to your advice like this and it worked great :)
[TestFixture]
public class PersistenceTest
{
protected ISession Session;
protected ITransaction Transaction;
[SetUp]
public void SetUp()
{
var helper = new NHibernateHelper("...connectionString....");
Session = helper.SessionFactory.OpenSession();
Transaction = Session.BeginTransaction();
}
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
Session.Save(entity);
Transaction.Commit();
var fromDb = Session.Get<T>(entity.Id);
return fromDb;
}
}

Unittest SignalR Hubs

I Would like to test my Hub in SignalR, what is the best approach?
Possible solutions I have thought about so far:
Create a testable Hub
Abstract logic to separate class
Selenium (would like to test smaller units)
Or is it some SignalR testing features have overlooked
Currently using SignalR 0.4, and NUnit as the testing framework.
This link shows how to unit test SignalR hub methods using Moq. You mock up the respository, clients, context, and the caller. Here's the code from the site, I made some minor changes to make it work with the latest SignalR:
public class TestableChatHub : ChatHub
{
public Mock<IChatRepository> MockChatRepository { get; private set; }
public TestableChatHub(Mock<IChatRepository> mockChatRepository)
: base(mockChatRepository.Object)
{
const string connectionId = "1234";
const string hubName = "Chat";
var mockConnection = new Mock<IConnection>();
var mockUser = new Mock<IPrincipal>();
var mockCookies = new Mock<IRequestCookieCollection>();
var mockRequest = new Mock<IRequest>();
mockRequest.Setup(r => r.User).Returns(mockUser.Object);
mockRequest.Setup(r => r.Cookies).Returns(mockCookies.Object);
Clients = new ClientProxy(mockConnection.Object, hubName);
Context = new HubCallerContext(mockRequest.Object, connectionId);
var trackingDictionary = new TrackingDictionary();
Caller = new StatefulSignalProxy(
mockConnection.Object, connectionId, hubName, trackingDictionary);
}
}
Then the site shows that you can use this testable hub to write unit tests:
[TestClass]
public class ChatHubTests
{
private TestableChatHub _hub;
public void SetUpTests()
{
_hub = GetTestableChatHub();
}
[Test]
public void ExampleTest()
{
SetUpTests();
const string message = "test";
const string connectionId = "1234";
var result = _hub.Send(message);
_hub.MockChatRepository.Verify(r => r.SaveMessage(message, connectionId));
Assert.IsTrue(result);
}
private TestableChatHub GetTestableChatHub()
{
var mockRepository = new Mock<IChatRepository>();
mockRepository.Setup(m => m.SaveMessage(
It.IsAny<string>(), It.IsAny<string())).Returns(true);
return new TestableChatHub(mockRepository);
}
}
It's quite simple to create to unit test SignalR hubs using a couple of neat tricks. One thing to note is that SignalR uses dynamic classes which might not be supported by your mocking framework (I use NSubstitute).
public class ProjectsHub: Hub
{
public void AddProject(string id)
{
Clients.All.AddProject(id);
}
}
[TestFixture]
public class ProjectsHubTests
{
// Operations that clients might receive
// This interface is in place in order to mock the
// dynamic object used in SignalR
public interface ISignals
{
void AddProject(string id);
}
[Test]
public void AddProject_Broadcasts()
{
// Arrange
ProjectsHub hub = new ProjectsHub();
IHubCallerConnectionContext clients =
Substitute.For<IHubCallerConnectionContext>();
ISignals signals = Substitute.For<ISignals>();
SubstituteExtensions.Returns(clients.All, signals);
hub.Clients = clients;
// Act
hub.AddProject("id");
// Assert
signals.Received(1).AddProject("id");
}
}
Rewriting this to use e.g. Moq should be pretty simple.
This question is from a while ago, but I'll do my best to answer anyway.
If you have a lot of logic in your actual hub class, it would certainly make sense to abstract the logic to a separate class. I did the same for my SignalR-powered multiplayer demo. The only behaviour that should go in your hub class itself is the one related to messaging. All further action should be delegated.
Note: This is very much like the guidelines for controller design in ASP .NET MVC: Keep your controllers small and delegate the real work.
If you want integration tests with SignalR actually doing some work, selenium webdriver would be a good option. But you will probably need to do some tweaking to get the SignalR messaging working perfectly in the context of the tests. Do a google search for "signalr selenium" (without the quotes) to get started on the right track.
Some blogposts about automated tests for SignalR => here and here
With the SignalR 2.0 you can do it this way:
// Arrange
var hub = new CodeInteractivePreviewHub();
var mockClients = new Mock<IHubCallerConnectionContext<dynamic>>();
hub.Clients = mockClients.Object;
dynamic all = new ExpandoObject();
mockClients.Setup(m => m.All).Returns((ExpandoObject)all);
// Act
var allSourceCodes = hub.InitiateCommunication(); //Change this line to your Hub's method
// Assert
Assert.IsNotNull(allSourceCodes);
This is modified version of Iarsm's answer, to work with XUnit and MOQ.
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Moq;
using Xunit;
namespace TestLibrary {
public class ProjectsHub : Hub {
public void AddProject(string id) {
Clients.All.AddProject(id);
}
}
public class ProjectsHubTests {
// Operations that clients might receive
// This interface is in place in order to mock the
// dynamic object used in SignalR
public interface ISignals {
void AddProject(string id);
}
[Fact]
public void AddProject_Broadcasts() {
// Arrange
ProjectsHub hub = new ProjectsHub();
var clients = new Mock<IHubCallerConnectionContext<dynamic>>();
var signals = new Mock<ISignals>();
hub.Clients = clients.Object;
signals.Setup(m => m.AddProject(It.Is<string>(s => s == "id"))).Verifiable();
clients.Setup(m => m.All).Returns(signals.Object);
// Act
hub.AddProject("id");
// Assert
signals.VerifyAll();
}
}
}
My interface was out of the test project, but here's how I did it using NUnit and Moq.
using Microsoft.AspNetCore.SignalR;
using Moq;
using NUnit.Framework;
namespace TestLibrary
{
// Operations that clients might receive
// This interface is in place in order to mock the
// dynamic object used in SignalR
public interface ISignals
{
void AddProject(string id);
}
public class ProjectsHub : Hub<ISignals>
{
public void AddProject(string id)
{
Clients.All.AddProject(id);
}
}
public class ProjectsHubTests
{
[Test]
public void AddProject_Broadcasts()
{
// Arrange
ProjectsHub hub = new ProjectsHub();
var clients = new Mock<IHubCallerClients<ISignals>>();
var signals = new Mock<ISignals>();
hub.Clients = clients.Object;
signals.Setup(m => m.AddProject(It.Is<string>(s => s == "id"))).Verifiable();
clients.Setup(m => m.All).Returns(signals.Object);
// Act
hub.AddProject("id");
// Assert
signals.VerifyAll();
}
}
}

Creating Code-Activity unit test while using GetExtension

How do I create unit test with context based on integration component?
I have identified problem as the Extension is trying to resolve implementation and returning error message:
"Object reference not set to an instance of an object."
My class:
public sealed class GetListOfServiceIdsToProcess
{
public InOutArgument<IArguments> Arguments { get; set; }
protected override void Execute(CodeActivityContext context)
{
// I am recieving my error exception here
context.GetExtension<lib.Extension.MyExtenstion>();
var targetIds= (List<int>)Settings.Get("targetIds");
var wfa = this.Arguments.Get(context);
wfa.ListTargetIds = targetIds;
Arguments.Set(context, wfa);
}
}
My Test so far:
I have problem with implementation of the test as far i could get it:
/// <summary>
///A test for Execute
///</summary>
[TestMethod()]
public void ExecuteTest()
{
// create Isettings mock to return collection of service ids
var expected = new List<int>() { 30, 20 };
var wfaInput = new TestWorkFlow();
var serviceIdList = new GetListOfServiceIdsToProcess();
var wfParam = new Dictionary<string, object>();
wfParam.Add("WorkFlowArguments", wfaInput);
var results = WorkflowInvoker.Invoke(serviceIdList, wfParam);
var wfaResult = (IWorkFlowArguments)results["WorkFlowArguments"];
Assert.AreEqual(expected, wfaResult.ListOfServiceIdsToProcess);
}
Instead of using the static WorkflowInvoker.Invoke() new up a WorkflowInvoker instance and add a mock, or whatever is needed for your test, lib.Extension.MyExtenstion to the Extensions collection.
[TestMethod]
public void ExecuteTest()
{
// ...
var invoker = new WorkflowInvoker(activityToTest);
// This way your extension will be available during execution
invoker.Extensions.Add(new MyExtension());
var results = invoker.Invoke(inputArgs);
// ....
}
I have run through multiple options and the problem what I have is MS Workflow.
I have extracted all logic away from workflow code activity into separate class and this class has been put under tests.
This is the best I could do for this. As I have base classes, that are injected, but I could not easily implement what I needed.
Thank you all for help anyway.

How do you test an extension method on an Interface which calls another method in that Interface with a mock created by Rhino Mocks?

I'm testing an extension method on an interface 'ISomeInterface'. The extension method actually calls to another method in the interface.
How do I set up a mock and the appropriate expectations (i want to set the expectation that 'SomeMethod', which is an defined method in the interface with a different signature then this extension method, will be called with 'someDifferentParam')
// Extension Method
public static ISomeInterface SomeMethod(this ISomeInterface someInterface, string someParam)
{
// do work, then call the defined method in the interface
someInterface.SomeMethod(int someDifferentParam)
return someInterface;
}
// tried to do the following but it errors
[Test]
public void SomeMethod_WithSomeInterface_CallsOtherSomeMethod()
{
const string someParam = "something";
const int someOtherParam = 1;
var mock = MockRepository.GenerateMock<ISomeInterface>();
mock.SomeMethod(someParam);
mock.AssertWasCalled(x => x.SomeMethod(someOtherParam));
}
EDIT
I finally got it working, but I'm open to suggestions/criticism. I'm just learning the ins/outs of Rhino Mocks myself =)
here is the real thing that I was testing. Since you can't compare two NHibernate.Criterion.Order objects by doing an Is.Equal or Is.SameAs I had to capture the arguments passed to the method call and then Assert on the ToString of the Order object because there are no public properties exposed on it.
// Extension Method
public static class NHibernateExtensions
{
public static ICriteria AddOrder(this ICriteria criteria, params OrderBy[] orderBys)
{
foreach (var b in orderBys)
{
var arr = b.Property.Split(',');
for (var i = 0; i < arr.Length; i++)
{
criteria.AddOrder(b.Direction == OrderDirection.Ascending
? Order.Asc(arr[i])
: Order.Desc(arr[i]));
}
}
return criteria;
}
}
// here is the test that works
[TestFixture]
public class NHibernateExtensionsTester : TestBase
{
[Test]
public void AddOrder_1OrderBy_CallsAddOrderOnICriteriaWithCorrectOrder()
{
const string testProperty = "SomeProperty";
var expected = (Order.Asc(testProperty)).ToString();
var orderBys = new[]
{
new OrderBy
{
Direction = OrderDirection.Ascending,
Property = testProperty
}
};
var mockCriteria = M<ICriteria>();
mockCriteria.AddOrder(orderBys);
var orderArgument = (Order)((mockCriteria.GetArgumentsForCallsMadeOn(x => x.AddOrder(null)))[0][0]);
Assert.That(orderArgument.ToString(), Is.EqualTo(expected));
}
}
Jon, since in effect you're just testing your extension method I see nothing wrong and this. I tried your code out and worked fine for me. Here is the exact code that I ran (using xunit.net and TD.Net). The test passed.
What error are you getting?