Nancy OWIN test interaction - c#

I'm trying to figure out why our integration tests are not independent.
The essential part of each test is:
var builder = new ContainerBuilder();
// IoC registrations, typically SingleInstance lifetimes or RegisterInstance
var browser = new Browser(new CustomBootstrapper(builder));
// browser.Post...
// Assertions
Each test uses fresh ContainerBuilder and Browser instances.
One of our tests passes when run independently, but fails if run along with another similar test. This happens in two different test runners (TestDriven.Net and JetBrains).
Instrumenting, I can see by checking HashCodes that an object used by the first test and injected by the IoC container shows up in the second test (and doesn't match the object created there). Methods are called on the wrong object, so the test fails.
The code doesn't use static members.
Am I misunderstanding something about the way Nancy, Nancy.Testing, or OWIN works? How can these tests influence each other?
Per request, more details:
[Test]
public void Test1()
{
var organizationCache = new OrganizationCache();
// Logs Creating OrganizationCache with HashCode:43641814 (varies by run)
organizationCache.AddOrganization(organization);
ContainerBuilder builder = AutofacTestContainerBuilderFactory.CreateTestContainerBuilder();
builder.RegisterInstance(organizationCache);
var browser = new Browser(new CustomBootstrapper(builder));
BrowserResponse browserResponse = browser.Post(
"/api/...",
with => with.JsonBody(model));
browserResponse.StatusCode.ShouldBe(HttpStatusCode.OK);
}
In separate TestFixture class, with no setup/teardown on either:
[Test]
public void Test2()
{
var organizationCache = new OrganizationCache();
// Logs Creating OrganizationCache with HashCode:5337202 (varies by run)
organizationCache.AddOrganization(organization);
ContainerBuilder builder = AutofacTestContainerBuilderFactory.CreateTestContainerBuilder();
builder.RegisterInstance(organizationCache);
var browser = new Browser(new CustomBootstrapper(builder));
TestHelpers.Authenticate(browser); // log in (does a browser.Post)
BrowserResponse browserResponse = browser.Post(
"/api/...",
with => with.JsonBody(model));
browserResponse.StatusCode.ShouldBe(HttpStatusCode.Created);
// Passes if run independently, fails if run with other test
// When run with other test, system under test logs both OrganizationCache HashCodes during this test
}
Could CookieBasedSessions somehow be affecting this? (Note: I tried removing CookieBasedSessions.Enable and- separately and together- creating a new Session in the pipeline; this did not affect the issue.)
Disposing of the customBootstrapper after each test made no difference either.
(CustomBootstrapper has no static fields and descends from AutofacNancyBootstrapper. It's too long to post here.)

One of our developers found the issue in our code.
using Nancy.Authentication.Forms;
public class UserMapper : IUserMapper
{
public static IOrganizationService OrganizationService { get; set; }
// ...
}
The implementation of IOrganizationService has an OrganizationCache injected into its constructor.
The static field was the culprit.

Related

Autofixture.NSubstitute check received calls without freezing

I have a sut with the dependency:
public interface IDep
{
void Click(int c);
}
public class Sut
{
public Sut(IDep dep)
{
dep.Click(10);
}
}
in my test I want to check that Click was called, but it does not work without being frozen.
var fixture = new Fixture().Customize(
new AutoNSubstituteCustomization { ConfigureMembers = true }
);
//fixture.Freeze<IDep>(); // uncommenting this line make it working
fixture.Create<Sut>();
fixture.Freeze<IDep>()
.Received(1)
.Click(Arg.Any<int>);
in my test I want to check that Click was called, but it does not work without being frozen.
That is by design. That freeze line is necessary to capture a single mocked dependency.
In this case the dependency injected into the SUT and the one you try to get after with the freeze will be different instances. Which is why your particular test case fails.
I would suggest keeping the first line and pass the returned value to a variable. You can then perform your assertion on the variable after exercising the SUT in this particular case.
For example
var fixture = new Fixture().Customize(
new AutoNSubstituteCustomization { ConfigureMembers = true }
);
//Arrange
IDep dependency = fixture.Freeze<IDep>();
//...any configuration needed on the mock can be done here
//Act
Sut sut = fixture.Create<Sut>(); //frozen dependency will be injected into sut.
//Assert
dependency.Received(1).Click(Arg.Any<int>);
I suggest reviewing the Quick Start to get a better understanding of what is the purpose of the Freeze functionality
Luckily we can tell our fixture to “freeze” a particular type. This means that every time we request an instance of a frozen type, we will get the same instance. You can think of it as registering a singleton instance in an IoC container.

Why is the WebApplicationFactory not resetting between tests?

I have two tests of an ASP.NET core webapp within a single test class. The class uses an IClassFixture<WebApplicationFactory<Startup>>.
The first test is a happy path test: when a message arrives on a Kafka topic, some file appears in a particular output directory.
The second test is to verify that if something goes wrong with outputting said file, the webapp should then be in an unhealthy status.
For brevity, I'm omitting the code that publishes to Kafka and that generates the output folder the application saves files to - neither of these are relevant.
[CollectionDefinition("e2e", DisableParallelization = true)]
[Trait("Category", "IntegrationTest")]
public class EndToEndTest : IClassFixture<WebApplicationFactory<Startup>>, IClassFixture<KafkaFixture>
{
private readonly WebApplicationFactory<Startup> _factory;
public EndToEndTest(WebApplicationFactory<Startup> factory)
{
_factory = factory;
KafkaUtils.Publish(SomeMessage()).GetAwaiter().GetResult();
}
[Fact]
public void WhenXReceived_ThenFileIsOutput()
{
var options = OutputFolder();
Directory.CreateDirectory(options.Path);
RunService(services => services.AddSingleton(Options.Create(options))).CreateClient();
Thread.Sleep(10_000);
var outputDirectory = Directory.GetFiles(options.Path);
Assert.Single(outputDirectory);
var file = outputDirectory.Single();
Assert.NotEmpty(File.ReadAllLinesAsync(file).GetAwaiter().GetResult());
Directory.Delete(options.Path, true);
}
[Fact]
public void WhenFileTransferFails_ThenAppShouldBeUnhealthy()
{
var options = OutputFolder();
// only try once, so we don't have to wait
var retry = new RetryPolicyConfiguration {OnErrorRetryCount = 1};
var factory = RunService(services =>
{
services.AddSingleton(Options.Create(options));
services.AddSingleton(Options.Create(retry));
services.RemoveAll<IFileWriter>();
services.AddScoped<IFileWriter, ThrowingFileWriter>();
});
var client = factory.CreateClient();
Thread.Sleep(10_000);
Assert.False(Directory.Exists(options.Path));
var response = client.GetAsync("/health/ready").GetAwaiter().GetResult();
var stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult();
using var reader = new StreamReader(stream);
var body = reader.ReadToEndAsync().GetAwaiter().GetResult();
var health = JsonConvert.DeserializeObject<HealthCheckResult>(body);
Assert.NotEqual(HealthStatus.Healthy, health.Status);
}
protected WebApplicationFactory<Startup> RunService(Action<IServiceCollection> serviceConfig)
{
return _factory
.WithWebHostBuilder(builder => builder
.ConfigureTestServices(services =>
{
serviceConfig(services);
services.AddSubscribeBus(new ConfigurationBuilder()
.AddJsonFile(ConfigMapFileProvider.FromRelativePath("config"),
"appsettings.e2e.json", true, true)
.Build());
}));
}
}
public class ThrowingFileWriter : IFileWriter
{
public void Write(string fileName, envelope envelope)
{
throw new Exception("foo");
}
public void Delete(string fileName)
{
}
}
If I run WhenFileTransferFails_ThenAppShouldBeUnhealthy() (unhealthyTest from here on, for brevity) on its own, then the test passes. But if I run the entire test class, then WhenXReceived_ThenFileIsOutput() (healthyTest, for brevity) runs before it, and for some reason unhealthyTest seems to use the service context that was created for healthyTest.
I've tried my best to work out what's going on, but it doesn't make sense to me. When I debug through it, the order of events is roughly as follows:
healthyTest starts
Startup invoked for healthytest
Constructor of service that uses IFileWriter is invoked with real instance of service
healthyTest completes
unhealthyTest starts
Constructor of service that uses IFileWriter is invoked with real instance of service (???)
Startup invoked for unhealthyTest
serviceConfig action invoked for unhealthyTest: all implementations of IFileWriter replaced with ThrowingFileWriter - but this is too late, it's already been constructed with the real instance in step 6
Consequently, the real service is used instead of the throwing service, and the exception handler that sets the app status to Unhealthy is never invoked.
Originally this was all running asynchronously, but I thought that perhaps the async nature of the tests meant that the two were conflicting with the webapp created by the factory - hence all the GetAwaiter().GetResult().
What am I doing wrong in my setup of the webapp for the test?
Note: it's unfortunately absolutely not an option to move these tests into their own test classes.

Test to verify if the dependency registered correctly in windsor

I have a class which inherited from IWindsorInstaller. I use this class to install/register the dependencies. Now I want to write tests for this class.
I register in the container a dependency with parameter. Like this:
container.Register(Component.For<IXService>().ImplementedBy<XService>().DependsOn(Dependency.OnComponent("operationY", "OperationY")).LifeStyle.Singleton);
Now in my Unit-Test, I want to verify if it is registered correctly. Something like this:
_containerMock.Verify(f=>f.Register(It.IsAny<ComponentRegistration<IXService>>().ImplementedBy<XService>().DependsOn(Dependency.OnComponent("operationY", "OperationY")).LifestyleSingleton()),Times.AtLeastOnce);
I don't have any idea, what should I do?
Thanks in advance, Mo.
Your unit test is not there to prove that the container has a registration for a given service.
It's to prove that the container can resolve that service (the fact that a registration exists is an implementation detail).
So, in your unit test, just attempt to resolve your service and verify it's what you are looking for, e.g:
public void UnitTest_Prove_That_Service_Can_Be_Created()
{
var sut = new SystemUnderTest();
var container = sut.GetContainer();
var service = container.Resolve<IXService>();
// Prove the IXService resolves to an XService - i.e. the registration
// has the correct mapping.
Assert.Type<XService>(service);
}
Additionally, you might want to prove it's a singleton:
public void UnitTest_Prove_That_Service_Is_A_Singleton()
{
var sut = new SystemUnderTest();
var container = sut.GetContainer();
var service1 = container.Resolve<IXService>();
var service2 = container.Resolve<IXService>();
// Prove you got the same service back each time - i.e. it's a singleton
Assert.Equals(service1, service2);
}
EDIT
The fact that the SUT is an IWindsorInstaller doesn't really change my answer. Just tweak the unit test slightly:
public void UnitTest_Prove_That_Service_Can_Be_Created()
{
var container = new WindsorContainer();
container.Install(new SystemUnderTest());
var service = container.Resolve<IXService>();
// Prove the IXService resolves to an XService - i.e. the registration
// has the correct mapping.
Assert.Type<XService>(service);
}

Transitioning to AutofacWebApiDependencyResolver from MVC's DependencyResolver - Where is .Current?

I had AutoFac working properly with MVC4. I'm trying to transition to Web API 2. Here's what I've got for setting up AutoFac:
public class AutofacRegistrations
{
public static void RegisterAndSetResolver()
{
// Create the container builder.
var containerBuilder = new ContainerBuilder();
// Register the Web API controllers.
containerBuilder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Only generate one SessionFactory ever because it is expensive.
containerBuilder.Register(x => new NHibernateConfiguration().Configure().BuildSessionFactory()).SingleInstance();
// Everything else wants an instance of Session per HTTP request, so indicate that:
containerBuilder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerApiRequest();
containerBuilder.Register(x => LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType)).InstancePerApiRequest();
containerBuilder.RegisterType<NHibernateDaoFactory>().As<IDaoFactory>().InstancePerApiRequest();
containerBuilder.RegisterType<StreamusManagerFactory>().As<IManagerFactory>().InstancePerApiRequest();
// Build the container.
ILifetimeScope container = containerBuilder.Build();
// Create the depenedency resolver.
var dependencyResolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver;
}
}
I'm pretty confident all of that is correct. My problem arises when I'm trying to setup some test cases. My base class for my test cases isn't a controller so it isn't automatically passed anything. In MVC4 I did the following:
[SetUp]
public void SetUp()
{
HttpSimulator = new HttpSimulator().SimulateRequest();
Logger = DependencyResolver.Current.GetService<ILog>();
DaoFactory = DependencyResolver.Current.GetService<IDaoFactory>();
Session = DependencyResolver.Current.GetService<ISession>();
ManagerFactory = DependencyResolver.Current.GetService<IManagerFactory>();
}
[TearDown]
public void TearDown()
{
HttpSimulator.Dispose();
}
Unfortunately, there's no DependencyResolver.Current in WebAPI. So I'm left wondering how to do this properly?
This builds, but is NOT correct. I received the message "Session Closed!" when I try to execute a test case:
[SetUp]
public void SetUp()
{
using (var scope = GlobalConfiguration.Configuration.DependencyResolver.BeginScope())
{
// TODO: Consider initializing Helpers during setup to keep this DRY.
Logger = (ILog)scope.GetService(typeof(ILog));
DaoFactory = (IDaoFactory)scope.GetService(typeof(IDaoFactory));
Session = (ISession)scope.GetService(typeof(ISession));
ManagerFactory = (IManagerFactory)scope.GetService(typeof(IManagerFactory));
}
}
With WebAPI, you don't need access to the current resolver because the current dependency scope generally comes along with the inbound HttpRequestMessage. That message is also what's responsible for generating the new request scope.
You can see the code for this in the System.Net.Http.HttpRequestMessageExtensions.GetDependencyScope method.
One big thing you'll notice in WebAPI is that you don't actually need to set anything in global static values - that is, you don't need to set a global configuration/resolver because everything is instance-based now.
For testing, what this means is:
Your setup will create an HttpRequestMessage with the appropriate dependency resolver and configuration.
Your teardown will dispose of the HttpRequestMessage which will, in turn, dispose the dependency scopes, etc. down the line.
Individual tests will use HttpRequestMessage.GetDependencyScope() if they need to do manual resolution of something and the request message will be used to coordinate/pass around the scope.
In a more concrete fashion, it might look like:
private HttpRequestMessage _request;
[SetUp]
public void SetUp()
{
var builder = new ContainerBuilder();
// Register stuff.
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
var config = new HttpConfiguration();
config.DependencyResolver = resolver;
config.EnsureInitialized();
this._request = new HttpRequestMessage();
this._request.SetConfiguration(config);
}
[TearDown]
public void TearDown()
{
this._request.Dispose();
}
[Test]
public void Test()
{
// When you need to resolve something, use the request message
this._request.GetDependencyScope().GetService(typeof(TheThing));
}
What's nice about this is that you don't have to fight with global configuration settings or resetting static values after every test.
You might wonder why you'd pass around the whole request message rather than just the dependency resolver - the reason is that the request message is what coordinates and controls the lifetime of the dependency scope. Otherwise, when you call GetDependencyScope multiple times, you'll get multiple different scopes rather than the same one as you'd expect.
Some things to consider from a design perspective:
You might want to put the actual registrations of things into an Autofac module so it can be reused in both tests and in your RegisterAndSetResolver method without having to worry about global statics getting tampered with.
Instead of a RegisterAndSetResolver modifying the global static configuration, you might consider just setting the resolver on the HttpConfiguration object that gets wired up in that WebApiConfig.Register method that WebAPI gives you. Take an HttpConfiguration object in as a parameter and set the resolver on that rather than the global.
If you're doing every registration for everything in a unit test, your unit tests might be closer to "integration tests." You might consider looking at only what's required for the stuff you're testing and using a mock framework to register stubs rather than actually registering a boatload of "real stuff."
Anyway, HttpRequestMessage is the way to go for WebAPI.

MEF creation policy

I am attempting to use the shared part creation policy for a MEF export. It does not, however, seem to work the way I was thinking. I do the composition twice in my application and each time get a fresh copy of the object. I've proved this by adding an instance counter to the object instanciation
static int instCount = 0;
public FakeAutocompleteRepository()
{
instCount++;
...
}
and running it all in debug. Indeed the second time I do a composition I get a new copy of the FakeAutocompleteRepository with instCount = 2. The export section contains
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(IAutocompleteRepository))]
[ExportMetadata("IsTesting", "True")]
class FakeAutocompleteRepository : IAutocompleteRepository
{ ... }
Is there some trick to getting the same instance for subsiquent requests? In case it is something I'm doing during the composition this is how I'm doing that
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog("."));
var container = new CompositionContainer(catalog);
var batch = new CompositionBatch();
batch.AddPart(this);
container.Compose(batch);
if (null != ConfigurationSettings.AppSettings["IsTesting"] && bool.Parse(ConfigurationSettings.AppSettings["IsTesting"]))
repository = container.GetExports<IAutocompleteRepository>().Where(expDef => expDef.Metadata.Keys.Contains("IsTesting")).Single().GetExportedObject();
Basically I'm trying to force a specific composition during testing. If you have a better idea for unit testing these compositions then I'm all ears.
I don't see anything specifically in your code that would cause more than one of your part to be created. Are you creating a different container for each composition? If you are, that is why you are getting separate instances.
As far as how to combine composition and unit testing in general, there is some discussion of this here.
What I did for unit testing was avoid composition. For instance (I'm using WPF and MVVM here), let's say you want to test this ViewModel:
[Export("/MyViewModel")]
public class MyViewModel
{
[ImportingConstructor]
public MyViewModel(
[Import("/Services/LoggingService")] ILoggingService l)
{
logger = l;
}
private ILoggingService logger { get; set; }
/* ... */
}
I don't want to instantiate the full-blown logging service every time I do a unit test, so I have a MockLoggingService class that implements ILoggingService and it just swallows all the log messages, (or checks that the proper messages are being generated, if you care). Then I can do this in my unit test:
MyViewModel target = new MyViewModel(new MockLoggingService());

Categories