How to write test using xUnit for service layer? - unit-testing

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 :-)

Related

How to create Masstransit's Test Harness with Automock?

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);

Unit testing web api controller with role based authorization [duplicate]

I have an ASP.NET MVC Core application that I am writing unit tests for. One of the action methods uses User name for some functionality:
SettingsViewModel svm = _context.MySettings(User.Identity.Name);
which obviously fails in the unit test. I looked around and all suggestions are from .NET 4.5 to mock HttpContext. I am sure there is a better way to do that. I tried to inject IPrincipal, but it threw an error; and I even tried this (out of desperation, I suppose):
public IActionResult Index(IPrincipal principal = null) {
IPrincipal user = principal ?? User;
SettingsViewModel svm = _context.MySettings(user.Identity.Name);
return View(svm);
}
but this threw an error as well.
Couldn't find anything in the docs either...
The controller’s User is accessed through the HttpContext of the controller. The latter is stored within the ControllerContext.
The easiest way to set the user is by assigning a different HttpContext with a constructed user. We can use DefaultHttpContext for this purpose, that way we don’t have to mock everything. Then we just use that HttpContext within a controller context and pass that to the controller instance:
var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, "example name"),
new Claim(ClaimTypes.NameIdentifier, "1"),
new Claim("custom-claim", "example claim value"),
}, "mock"));
var controller = new SomeController(dependencies…);
controller.ControllerContext = new ControllerContext()
{
HttpContext = new DefaultHttpContext() { User = user }
};
When creating your own ClaimsIdentity, make sure to pass an explicit authenticationType to the constructor. This makes sure that IsAuthenticated will work correctly (in case you use that in your code to determine whether a user is authenticated).
In previous versions you could have set User directly on the controller, which made for some very easy unit tests.
If you look at the source code for ControllerBase you will notice that the User is extracted from HttpContext.
/// <summary>
/// Gets the <see cref="ClaimsPrincipal"/> for user associated with the executing action.
/// </summary>
public ClaimsPrincipal User => HttpContext?.User;
and the controller accesses the HttpContext via ControllerContext
/// <summary>
/// Gets the <see cref="Http.HttpContext"/> for the executing action.
/// </summary>
public HttpContext HttpContext => ControllerContext.HttpContext;
You will notice that these two are read only properties. The good news is that ControllerContext property allows for setting it's value so that will be your way in.
So the target is to get at that object. In Core HttpContext is abstract so it is a lot easier to mock.
Assuming a controller like
public class MyController : Controller {
IMyContext _context;
public MyController(IMyContext context) {
_context = context;
}
public IActionResult Index() {
SettingsViewModel svm = _context.MySettings(User.Identity.Name);
return View(svm);
}
//...other code removed for brevity
}
Using Moq, a test could look like this
public void Given_User_Index_Should_Return_ViewResult_With_Model() {
//Arrange
var username = "FakeUserName";
var identity = new GenericIdentity(username, "");
var mockPrincipal = new Mock<ClaimsPrincipal>();
mockPrincipal.Setup(x => x.Identity).Returns(identity);
mockPrincipal.Setup(x => x.IsInRole(It.IsAny<string>())).Returns(true);
var mockHttpContext = new Mock<HttpContext>();
mockHttpContext.Setup(m => m.User).Returns(mockPrincipal.Object);
var model = new SettingsViewModel() {
//...other code removed for brevity
};
var mockContext = new Mock<IMyContext>();
mockContext.Setup(m => m.MySettings(username)).Returns(model);
var controller = new MyController(mockContext.Object) {
ControllerContext = new ControllerContext {
HttpContext = mockHttpContext.Object
}
};
//Act
var viewResult = controller.Index() as ViewResult;
//Assert
Assert.IsNotNull(viewResult);
Assert.IsNotNull(viewResult.Model);
Assert.AreEqual(model, viewResult.Model);
}
There is also the possibility to use the existing classes, and mock only when needed.
var user = new Mock<ClaimsPrincipal>();
_controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext
{
User = user.Object
}
};
In my case, I needed to make use of Request.HttpContext.User.Identity.IsAuthenticated, Request.HttpContext.User.Identity.Name and some business logic sitting outside of the controller. I was able to use a combination of Nkosi's, Calin's and Poke's answer for this:
var identity = new Mock<IIdentity>();
identity.SetupGet(i => i.IsAuthenticated).Returns(true);
identity.SetupGet(i => i.Name).Returns("FakeUserName");
var mockPrincipal = new Mock<ClaimsPrincipal>();
mockPrincipal.Setup(x => x.Identity).Returns(identity.Object);
var mockAuthHandler = new Mock<ICustomAuthorizationHandler>();
mockAuthHandler.Setup(x => x.CustomAuth(It.IsAny<ClaimsPrincipal>(), ...)).Returns(true).Verifiable();
var controller = new MyController(...);
var mockHttpContext = new Mock<HttpContext>();
mockHttpContext.Setup(m => m.User).Returns(mockPrincipal.Object);
controller.ControllerContext = new ControllerContext();
controller.ControllerContext.HttpContext = new DefaultHttpContext()
{
User = mockPrincipal.Object
};
var result = controller.Get() as OkObjectResult;
//Assert results
mockAuthHandler.Verify();
I want to hit my Controllers directly and just use DI like AutoFac. To do this I first registering ContextController.
var identity = new GenericIdentity("Test User");
var httpContext = new DefaultHttpContext()
{
User = new GenericPrincipal(identity, null)
};
var context = new ControllerContext { HttpContext = httpContext};
builder.RegisterInstance(context);
Next I enable property injection when I register the Controllers.
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith("Controller")).PropertiesAutowired();
Then User.Identity.Name is populated, and I do not need to do anything special when calling a method on my Controller.
public async Task<ActionResult<IEnumerable<Employee>>> Get()
{
var requestedBy = User.Identity?.Name;
..................
I would look to implement an Abstract Factory Pattern.
Create an interface for a factory specifically for providing user names.
Then provide concrete classes, one which provides User.Identity.Name, and one that provides some other hard coded value that works for your tests.
You can then use the appropriate concrete class depending on production versus test code. Perhaps looking to pass the factory in as a parameter, or switching to the correct factory based on some configuration value.
interface IUserNameFactory
{
string BuildUserName();
}
class ProductionFactory : IUserNameFactory
{
public BuildUserName() { return User.Identity.Name; }
}
class MockFactory : IUserNameFactory
{
public BuildUserName() { return "James"; }
}
IUserNameFactory factory;
if(inProductionMode)
{
factory = new ProductionFactory();
}
else
{
factory = new MockFactory();
}
SettingsViewModel svm = _context.MySettings(factory.BuildUserName());
I got a brownfield .net 4.8 project that I needed to convert to .net 5.0 and I wanted to keep as much of the original code as possible, including the unit-/integration tests. The test for Controllers relied on the Context a lot so I created this Extension method to enable setting tokens, claims and headers:
public static void AddContextMock(
this ControllerBase controller,
IEnumerable<(string key, string value)> claims = null,
IEnumerable<(string key, string value)> tokens = null,
IEnumerable<(string key, string value)> headers = null)
{
HttpContext mockContext = new DefaultHttpContext();
if(claims != null)
{
mockContext.User = SetupClaims(claims);
}
if(tokens != null)
{
mockContext.RequestServices = SetupTokens(tokens);
}
if(headers != null)
{
SetupHeaders(mockContext, headers);
}
controller.ControllerContext = new ControllerContext()
{
HttpContext = mockContext
};
}
private static void SetupHeaders(HttpContext mockContext, IEnumerable<(string key, string value)> headers)
{
foreach(var header in headers)
{
mockContext.Request.Headers.Add(header.key, header.value);
}
}
private static ClaimsPrincipal SetupClaims(IEnumerable<(string key, string value)> claimValues)
{
var claims = claimValues.Select(c => new Claim(c.key, c.value));
return new ClaimsPrincipal(new ClaimsIdentity(claims, "mock"));
}
private static IServiceProvider SetupTokens(IEnumerable<(string key, string value)> tokenValues)
{
var mockServiceProvider = new Mock<IServiceProvider>();
var authenticationServiceMock = new Mock<IAuthenticationService>();
var authResult = AuthenticateResult.Success(
new AuthenticationTicket(new ClaimsPrincipal(), null));
var tokens = tokenValues.Select(t => new AuthenticationToken { Name = t.key, Value = t.value });
authResult.Properties.StoreTokens(tokens);
authenticationServiceMock
.Setup(x => x.AuthenticateAsync(It.IsAny<HttpContext>(), null))
.ReturnsAsync(authResult);
mockServiceProvider.Setup(_ => _.GetService(typeof(IAuthenticationService))).Returns(authenticationServiceMock.Object);
return mockServiceProvider.Object;
}
This uses Moq but can be adapted to other mocking frameworks. The authentication type is hardcoded to "mock" since I rely on default authentication but this could be supplied as well.
It is used as such:
_controllerUnderTest.AddContextMock(
claims: new[]
{
(ClaimTypes.Name, "UserName"),
(ClaimTypes.MobilePhone, "1234"),
},
tokens: new[]
{
("access_token", "accessTokenValue")
},
headers: new[]
{
("header", "headerValue")
});
If you're using Razor pages and want to override the claims:
[SetUp]
public void Setup()
{
var user = new ClaimsPrincipal(new ClaimsIdentity(
new Claim[] {
new("dateofbirth", "2000-10-10"),
new("surname", "Smith") },
"mock"));
_razorModel = new RazorModel()
{
PageContext = new PageContext
{
HttpContext = new DefaultHttpContext() { User = user }
}
};
}

Where do you set the OrmLiteConfig.DialectProvider.NamingStrategy in a unit test?

I'm using both ORMLite and Dapper in a project and would like standardized on the naming conventions used by both ORMs. In order to do this I'd like to set the NamingStrategy as such:
OrmLiteConfig.DialectProvider.NamingStrategy = new OrmLiteNamingStrategyBase();
and a unit test to verify
public class BorrowerUnitTests : IDisposable
{
private readonly ServiceStackHost appHost;
public BorrowerUnitTests()
{
//Set ORMLite to work with columns like ColumnLikeThis
// OrmLiteConfig.DialectProvider.NamingStrategy = new OrmLiteNamingStrategyBase();
appHost = new BasicAppHost(typeof(BorrowerServices).Assembly)
{
ConfigureContainer = container =>
{
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(ConfigUtils.GetConnectionString("LoanOrigination:Default"), PostgreSqlDialect.Provider));
container.RegisterAutoWiredAs<Repository, IRepository>();
container.RegisterAutoWired<BorrowerDomainService>();
}
}
.Init();
}
public void Dispose()
{
appHost.Dispose();
}
[Fact]
public void TestPostMethod()
{
var service = appHost.Container.Resolve<BorrowerServices>();
BorrowerCreate request = new BorrowerCreate();
request.FirstName = "Orm";
request.LastName = "Lite";
request.Email = "ormlite#servicestack.net";
var response = service.Post(request);
Assert.True(response.Id > 0, "Id retured from POST cannot be zero");
}
[Fact]
public void TestGetMethod()
{
var service = appHost.Container.Resolve<BorrowerServices>();
BorrowerGet request = new BorrowerGet();
request.Id = 1;
var response = service.Get(request);
Assert.Equal("ormlite#servicestack.net", response.Email);
}
[Fact]
public void TestPutMethod()
{
var service = appHost.Container.Resolve<BorrowerServices>();
BorrowerUpdate request = new BorrowerUpdate();
request.Id = 5;
request.FirstName = "MyFirstName2";
request.LastName = "MyLastName2";
request.Email = "MyEmail#Example.com";
var response = service.Put(request);
Assert.True(response.FirstName == "MyFirstName2", "FirstName is noth equal");
}
}
No matter where I put the NamingStrategy statement, I get a exception from the DialectProvider property of the OrmLiteConfig class, "You must set the singleton 'OrmLiteConfig.DialectProvider' to use the OrmLiteWriteExtensions"
Where's the proper place to set this property?
Thank you,
Stephen
You can just assign it to the DialectProvider you're using, e.g:
PostgreSqlDialect.Provider.NamingStrategy = new OrmLiteNamingStrategyBase();
The OrmLiteConfig.DialectProvider is a singleton that can either be set manually:
OrmLiteConfig.DialectProvider = PostgreSqlDialect.Provider;
OrmLiteConfig.DialectProvider.NamingStrategy = new OrmLiteNamingStrategyBase();
Or implicitly with the new OrmLiteConnectionFactory() constructor, which to run, needs to resolved from the IOC:
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(...));
using (var db = container.Resolve<IDbConnectionFactory>().Open())
{
OrmLiteConfig.DialectProvider.NamingStrategy = new OrmLiteNamingStrategyBase();
}

How to reset autofac container?

In my tests I setup an autofac container, it returns some real implementation and some mocks (DB, external systems).
The problem is that after each test I Dispose the container and create a new one:
Autofac.IContainer.Dispose() and Container = builder.Build();
The already registered instances are still there.
How can I reset the container so it would be 'like new' again?
The reason why I want to do is - I want to replace one mocked instance with another. It's being registered as Singleton.
---- EDIT
Thanks for the answers. I decided to add some more code and describe what actually I'm trying to achieve. But that is actually a topic for another (prabably already answered question - unit testing CQRS).
My app contains static IContainer property:
public static IContainer Container { get; private set; }
After each test execution I create it again by calling those two methods:
public static ContainerBuilder Compose(IEnumerable<DependencyProvider> dependencyProviders)
{
var collection = dependencyProviders as List<DependencyProvider> ?? dependencyProviders.ToList();
var included = new HashSet<DependencyProvider>(collection);
var includedTypes = new HashSet<Type>(collection.Select(x => x.GetType()));
var currentWorkingSet = new List<DependencyProvider>(collection);
while (true)
{
var candidates = currentWorkingSet.SelectMany(x => x.GetDependencies());
var typesToBeAdded = candidates.Where(x => !includedTypes.Contains(x)).Distinct().ToList();
if (typesToBeAdded.Any() == false)
break;
currentWorkingSet.Clear();
foreach (var type in typesToBeAdded)
{
includedTypes.Add(type);
var instance = CreateInstance(type);
included.Add(instance);
currentWorkingSet.Add(instance);
}
}
return BuildContainer(included);
}
and
TestDependencyProvider dependencyProvider = new TestDependencyProvider()
var builder = Compose(new[] { dependencyProvider });
Container = builder.Build();
The TestDependencyProvider is created for each test and contains moqed instances. It registers those mocks and x.GetDependencies() uses the original container registrations i.e. container.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsClosedTypesOf(typeof(IAggregateBusinessRuleForEvent<,>));
The type I'm mostly interested in is one of implementations of IAggregateBusinessRuleForEvent<,>).
public class RuleA: IAggregateBusinessRuleForEvent<AEvent, Something>
{
private readonly IDependency _dependency;
public RejectCompanyNameRule(IDependency dependency)
{
_dependency = dependency;
}
}
So even though I create this container again that RuleA is still there and all of my test are using same instance with same _dependency :/
It's still not entierly clear why code looks how it looks, I'm trying to understand it by adding tests...
------- EDIT 2
Following Jimmy's advice I've implemented a sample using Update me
public interface IExample<T>
{
void Hello();
}
public interface IExampleDependecy
{
void SaySomething();
}
public class Example : IExample<string>
{
private IExampleDependecy _dependecy;
public Example(IExampleDependecy dependecy)
{
_dependecy = dependecy;
}
public void Hello()
{
Console.WriteLine("Hello");
_dependecy.SaySomething();
}
}
[TestMethod]
public void T()
{
// first test
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsClosedTypesOf(typeof(IExample<>));
var mockA = new Moq.Mock<IExampleDependecy>();
mockA.Setup(d => d.SaySomething()).Callback(() => Console.WriteLine("A"));
builder.RegisterInstance(mockA.Object).SingleInstance();
var container = builder.Build();
var sample1 = container.Resolve<IExample<string>>();
sample1.Hello();
// new test using same container
var updater = new ContainerBuilder();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsClosedTypesOf(typeof(IExample<>));
var mockB = new Moq.Mock<IExampleDependecy>();
mockB.Setup(d => d.SaySomething()).Callback(() => Console.WriteLine("B"));
builder.RegisterInstance(mockB.Object).SingleInstance();
updater.Update(container); // overwrites existing registrations
var sample2 = container.Resolve<IExample<string>>();
sample2.Hello();
}
and result is:
Hello
A
Hello
A
Autofac by default overrides previous registrations with subsequent ones. That means you don't have to do anything special apart from updating container with your new instance:
var builder = new ContainerBuilder();
builder.RegisterInstance(new Sample("A")).SingleInstance();
var container = builder.Build();
var sample = container.Resolve<Sample>();
// do your test
...
// new test using same container
var updater = new ContainerBuilder();
updater.RegisterInstance(new Sample("B")).SingleInstance();
updater.Update(container); // overwrites existing registrations
var sample = container.Resolve<Sample>(); // returns "B"

RhinoMocks - Unable to cast type foo to type bar when using non static Repository

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();