I trying to do in memory ef core testing.
I have something similar to this:
Startup
services.AddEntityFrameworkNpgsql().AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("PostgresConnection"), x=>x.UseNetTopologySuite()))
.BuildServiceProvider();
Test method
public void Add_writes_to_database()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "Add_writes_to_database")
.Options;
// Run the test against one instance of the context
using (var context = new ApplicationDbContext(options))
{
var service = new BlogService(context);
service.Add("http://sample.com");
}
// Use a separate instance of the context to verify correct data was saved to database
using (var context = new ApplicationDbContext(options))
{
Assert.AreEqual(1, context.Blogs.Count());
Assert.AreEqual("http://sample.com", context.Blogs.Single().Url);
}
}
When the context is split into 2 using blocks like above it does not pass the test.
But when its all wrapped in one context it works ok.
Any ideas?
Had to also iclude InMemoryDatabaseRoot
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString(),
databaseRoot: new InMemoryDatabaseRoot())
.Options;
Related
In order to create the test harness for the SubmitOrderConsumer, I will have to build a ServiceCollection containing all the depdencies of SubmitOrderConsumer.
Mock<INotifier> mockNotifier = new Mock<INotifier>();
Mock<IStockChecker> mockStockChecker = new Mock<IStockChecker>();
Mock<IFidelityUpdater> mockFidelityUpdater = new Mock<IFidelityUpdater>();
Mock<IPromotionManager> mockPromotionManager = new Mock<IPromotionManager>();
await using var provider = new ServiceCollection()
.AddMassTransitTestHarness(cfg =>
{
cfg.AddConsumer<SubmitOrderConsumer>();
})
.AddSingleton<INotifier>(mockNotifier.Object)
.AddSingleton<IStockChecker>(mockStockChecker.Object)
.AddSingleton<IFidelityUpdater>(mockFidelityUpdater.Object)
.AddSingleton<IPromotionManager>(mockPromotionManager.Object)
..
.BuildServiceProvider(true);ds
var harness = provider.GetRequiredService<ITestHarness>();
...
mockNotifier.Verify(...)
The Moq.Automock library helps me to create the SubmitOrderConsumer and auto-mock all its depdencies so the above codes is reduced to
AutoMocker mocker = new AutoMocker();
await using var provider = new ServiceCollection()
.AddMassTransitTestHarness(cfg =>
{
cfg.AddConsumer<SubmitOrderConsumer>();
})
.AddSingleton(mocker.CreateInstance<SubmitOrderConsumer>())
.BuildServiceProvider(true);
var harness = provider.GetRequiredService<ITestHarness>();
...
mocker.GetMock<INotifier>().Verify(...)
Question:
The class AutoMocker is also a IServiceProvider, so the above codes have 2 IServiceProvider:
the first IServiceProvider is the mocker which can resolve the SubmitOrderConsumer
the second IServiceProvider is the provider which can resolve the ITestHarness
is it possible to create the ITestHarness with my mocker IServiceProvider? something like
ITestHarness harness = new ContainerTestHarness(mocker);
How do I write a test using xUnit for a service layer? I'm using dependency injection for my service layer, but how can I make an instance of it using an in memory database?
Here is what I got so far: I follow this link and here is what I came up to use my service layer, but it was a mess and I don't know how to simplify it. I am using an interface of the service in all of my controllers.
[Fact]
public void Add_writes_to_database()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "Add_writes_to_database")
.Options;
// Run the test against one instance of the context
using (var context = new ApplicationDbContext(options))
{
var productRepo = new Repository<Product>(context);
var categoryRepo = new Repository<Category>(context);
var categoryMappingRepo = new Repository<ProductCategoryMapping>(context);
var categoryService = new CategoryService(context, categoryRepo, categoryMappingRepo);
var manufacturerRepo = new Repository<Manufacturer>(context);
var manufacturerMappingRepo = new Repository<ProductManufacturerMapping>(context);
var manufacturerService = new ManufacturerService(context, manufacturerRepo, manufacturerMappingRepo);
var imageRepo = new Repository<Image>(context);
var imageMappingRepo = new Repository<ProductImageMapping>(context);
var imageService = new ImageManagerService(imageRepo, imageMappingRepo);
var specificationRepo = new Repository<Specification>(context);
var specificationMappingRepo = new Repository<ProductSpecificationMapping>(context);
var specificationService = new SpecificationService(context, specificationRepo, specificationMappingRepo);
var productService = new ProductService(context, productRepo, categoryService, manufacturerService, imageService, specificationService);
var product = new Product() { Id = Guid.NewGuid(), Name = "Product1", Price = 100m };
productService.InsertProduct(product);
}
// Use a separate instance of the context to verify correct data was saved to database
using (var context = new ApplicationDbContext(options))
{
var productRepo = new Repository<Product>(context);
var categoryRepo = new Repository<Category>(context);
var categoryMappingRepo = new Repository<ProductCategoryMapping>(context);
var categoryService = new CategoryService(context, categoryRepo, categoryMappingRepo);
var manufacturerRepo = new Repository<Manufacturer>(context);
var manufacturerMappingRepo = new Repository<ProductManufacturerMapping>(context);
var manufacturerService = new ManufacturerService(context, manufacturerRepo, manufacturerMappingRepo);
var imageRepo = new Repository<Image>(context);
var imageMappingRepo = new Repository<ProductImageMapping>(context);
var imageService = new ImageManagerService(imageRepo, imageMappingRepo);
var specificationRepo = new Repository<Specification>(context);
var specificationMappingRepo = new Repository<ProductSpecificationMapping>(context);
var specificationService = new SpecificationService(context, specificationRepo, specificationMappingRepo);
var productService = new ProductService(context, productRepo, categoryService, manufacturerService, imageService, specificationService);
Assert.Equal(1, productService.GetAllProduct().Count());
}
}
My productService has lots of dependencies to other services, repository and context.
Yes, you have a lot of dependent services and repositories. Since you already use Dependency Injection for your services, I suggest that you make use of an IoC Container. This will not only remove lots of code to setup your integration tests, it will also help you to resolve any service in your application easily.
You could create a class for your type mappings like this:
public class Services
{
private readonly DbContextOptions _options;
private readonly IUnityContainer _container;
public Services(DbContextOptions options)
{
_options = options;
_container = new UnityContainer();
RegisterTypes();
}
private void RegisterTypes()
{
_container.RegisterType<IApplicationDbContext, ApplicationDbContext>(new ContainerControlledLifetimeManager(), new InjectionConstructor(_options));
_container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
_container.RegisterType<ISpecificationService, SpecificationService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IImageManagerService, ImageManagerService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IRepository<ProductSpecificationMapping>, Repository<ProductSpecificationMapping>>(new ContainerControlledLifetimeManager());
// etc ...
}
public T Get<T>()
{
return _container.Resolve<T>();
}
}
Then you are able to minimize the code in your test which is needed to resolve a product service:
[Fact]
public void Add_writes_to_database()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "Add_writes_to_database")
.Options;
var services = new Services(options);
var target = services.Get<IProductService>();
// to your testing
}
I haven't tested and verified these lines of code in VS, but it should give you an idea. We are using this approach with Unity in one of our application as well, and you can use your favorite IoC Container. You also need Interfaces for your Repositories and Services, but it is better to have them anyway :-)
I have following Unity configuration:
public static void RegisterTypes(IUnityContainer container)
{
...
container.RegisterType<IRootDatabaseContext, RootEntities>(new PerRequestLifetimeManager());
...
}
And everything works fine. But when I also want to test this method:
[TestMethod]
public void AssertUnityConfigAreValid()
{
using (var container = new UnityContainer())
{
UnityConfig.RegisterTypes(container);
foreach (var registration in container.Registrations)
{
container.Resolve(registration.RegisteredType, registration.Name);
}
}
}
And when I run this test I get an error:
InvalidOperationException - Operation is not valid due to the current state of the object.
How can I replace LifeTimeManager into Unit test from PerRequestLifetimeManager to another one?
I've just found the solution for this issue:
Just need to add following code before this line in test
UnityConfig.RegisterTypes(container);
var request = new HttpRequest("fake", "https://127.0.0.1", null);
var respons = new HttpResponse(new StringWriter());
var context = new HttpContext(request, respons);
HttpContext.Current = context;
I am trying out RhinoMocks (only just started, please be gentle!) and am confused as to why if I use this setup:
var mockRepos = new MockRepository();
var mockServiceProvider = mockRepos.DynamicMock<IServiceProvider>(null);
var mockContext = mockRepos.DynamicMock<IPluginExecutionContext>(null);
mockServiceProvider.Expect(x => x.GetService(typeof(IPluginExecutionContext))).Return(mockContext);
var someSampleClass = new SomeClassOrOther(mockServiceProvider);
At some point in SomeClassOrOther, the method GetService is called
var context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
and causes the exception:
Unable to cast object of type 'Castle.Proxies.ObjectProxyd0bf4b879a6341bbba3478cf1189d621' to type 'Microsoft.Xrm.Sdk.IPluginExecutionContext'.
However if I use:
var mockServiceProvider = MockRepository.GenerateMock<IServiceProvider>(null);
var mockContext = MockRepository.GenerateMock<IPluginExecutionContext>(null);
mockServiceProvider.Expect(x => x.GetService(typeof(IPluginExecutionContext))).Return(mockContext);
i.e. the static MockRepository.GenerateMock and it executes with no errors.
Where am I going wrong here?
I don't know why you are getting this very exception. However, when using the "old" non-static syntax, you get mocks in "Record" state. Before using them, you need to set them in Replay mode:
var mockRepos = new MockRepository();
var mockServiceProvider = mockRepos.DynamicMock<IServiceProvider>();
var mockContext = mockRepos.DynamicMock<IPluginExecutionContext>();
mockRepos.ReplayAll();
mockServiceProvider
.Stub(x => x.GetService(typeof(IPluginExecutionContext)))
.Return(mockContext);
var someSampleClass = new SomeClassOrOther(mockServiceProvider);
You are mixing new AAA syntax and old Record/Replay syntax. When you are using Expect extension method and new AAA syntax, you don't need to operate on mocks repository and change its mode manually(Record/Replay). Create mocks with new static methods (which create mocks in replay mode) and verify expectations later:
// Arrange
var mockServiceProvider = MockRepository.GenerateMock<IServiceProvider>();
var mockContext = MockRepository.GenerateMock<IPluginExecutionContext>();
mockServiceProvider.Expect(x => x.GetService(typeof(IPluginExecutionContext)))
.Return(mockContext);
var someSampleClass = new SomeClassOrOther(mockServiceProvider);
// Act
// Assert
mockServiceProvider.VerifyAllExpectations();
Here is old Record/Replay syntax for comparison:
var mockRepos = new MockRepository();
var mockServiceProvider = mockRepos.DynamicMock<IServiceProvider>();
var mockContext = mockRepos.DynamicMock<IPluginExecutionContext>();
Expect.Call(mockServiceProvider.GetService(typeof(IPluginExecutionContext)))
.Return(mockContext);
mockRepos.ReplayAll();
var someSampleClass = new SomeClassOrOther(mockServiceProvider);
// exercise your SUT
mockRepos.VerifyAll();
All,
I'm developing and unit testing an interactive voice application using ASP.NET MVC 3 whose controllers return Views containing VoiceXML. I'd like to create unit tests that capture the actual VoiceXML output so I can schema-validate it.
My reading and testing have taken me to Scott H's FakeHttpContext that uses Moq, as well as several responses here. Everything compiles correctly, and I'm trying to do something like the following:
[TestMethod]
public void WelcomeTest1()
{
EmergencyController controller = new EmergencyController();
controller.ControllerContext = new ControllerContext(MvcMockHelpers.FakeHttpContext("~/Emergency/Welcome"), new RouteData(), controller);
ViewResult result = (controller.Welcome()) as ViewResult;
.
.
Assert.IsTrue(controller.ControllerContext.HttpContext.Response.OutputStream.Length > 0);
// assert schema validation on the output here
}
However, stepping through this, I can see that the Welcome view being called, but I'm looking for something in the Response.Output and not finding anything. The mock is set up as follows, in hope that setting CallBase to true would actually write something out. I found some code that I added to the FakeHttpContext constructor that supposedly invokes a StringWriter, but to no avail:
public static HttpContextBase FakeHttpContext()
{
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>() { CallBase = true };
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
response.Setup(r => r.OutputStream).Returns(new MemoryStream());
response.Setup(r => r.Headers).Returns(new NameValueCollection());
var writer = new StringWriter();
var wr = new SimpleWorkerRequest("", "", "", "", writer);
HttpContext.Current = new HttpContext(wr);
return context.Object;
}
I'm sure I'm missing something obvious, but I'm stumped right now.
Thanks
Jim Stanley
Blackboard Connect
The result doesn't get populated in the ViewResult. In other words, the view isn't rendered by you calling return View() in your controller, rather mvc takes the viewresult and renders it at a later time in the request-sycle. What you need to do is to create a render-function for ViewResults, like this one:
using System;
using System.IO;
using System.Web.Mvc;
namespace CoPrice.Helpers
{
public static class ViewRendrer
{
public static string ToHtml(this ViewResult result, Controller controller)
{
controller.ViewData.Model = result.Model;
try
{
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, result.ViewName);
ViewContext context = new ViewContext(controller.ControllerContext, viewResult.View, result.ViewData, result.TempData, sw);
viewResult.View.Render(context, sw);
return sw.GetStringBuilder().ToString();
}
}
catch (Exception e)
{
return e.ToString();
}
}
}
}
Then you can do result.ToHtml(controller) to get the actual data (this works for RazorViews only I think, though I'm not sure, that's what I've used it for at least).