ServiceStack integration tests: ServiceStackHost.Instance has already been set - c#

I am writing integration tests for ServiceStack with in-memory database and I ran into this exception: "System.IO.InvalidDataException ServiceStackHost.Instance has already been set" while trying to run multiple test classes together, each having its own AppHostHttpListenerBase. However, if I ran the test classes one at a time, it ran and passed without problems. One reason for having multiple classes is because I want to test the AppHost with different services/dependencies registered and also to group my tests logically. Below is a general snippet of my tests. I would like to be able run all the test at one go.
public class TestClassOne : IDisposable
{
string _endPoint = "http://localhost:54321/";
AppHostHttpListenerBase _appHost;
IDbConnectionFactory _dbConn = new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider);
public TestClassOne()
{
_appHost = new UnitTestAppHost(_dbConn, ...){};
_appHost.Init().Start(_endPoint);
}
[Fact]
public void Test()
{
...
using(var db = _dbConn.Open())
{
Assert.True(...);
}
}
public void Dispose()
{
_appHost.Dispose();
_appHost = null;
}
}
public class TestClassTwo : IDisposable
{
string _endPoint = "http://localhost:54321/";
AppHostHttpListenerBase _appHost;
IDbConnectionFactory _dbConn = new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider);
public TestClassTwo()
{
_appHost = new UnitTestAppHost(...){};
_appHost.Init().Start(_endPoint);
}
[Fact]
public void Test()
{
...
using(var db = _dbConn.Open())
{
Assert.True(...);
}
}
public void Dispose()
{
_appHost.Dispose();
_appHost = null;
}
}
I have tried running on another AppDomain, but it doesn't seems to be what I am looking for I think, because I need to do some Asserts on IDbConnection in the current running AppDomain (?), if that make any sense. Any suggestions on how I should be doing it? I'm using xUnit and Resharper's test runner btw.

I ended up fixing this by creating an AppHostSetupFixture class with a public static AppHost variable. Create a [SetUp] method that initializes your app host and a [TearDown] method that disposes it. Use AppHostSetupFixture.AppHost in your test classes.
[SetUpFixture]
public class AppHostSetupFixture
{
public static ServiceStackHost AppHost;
[SetUp]
public void Setup()
{
AppHost = new BasicAppHost(typeof(FeatureService).Assembly)
{
ConfigureContainer = container =>
{
var l = new List<string>();
l.Add(ConfigurationManager.ConnectionStrings["Redis"].ConnectionString);
container.Register<IRedisClientsManager>(c => new RedisManagerPool(l, new RedisPoolConfig() { MaxPoolSize = 40 }));
}
}
.Init();
}
[TearDown]
public void TearDown()
{
AppHost.Dispose();
}
}

This error is a result of trying to run multiple AppHosts per AppDomain. Each ServiceStack AppHost is a singleton and only allows a single AppHost per AppDomain.

Related

C# UnitTest void static method

I'm trying to make an unit test for a logger in an application.
For example I need to test the method Logger.info("some message"), but this method is static and return void.
Searching on Google I understand that I have to use Moq but am unable to implement that on the UnitTest class.
The Logger constructor does not have an argument and in x.Debug I have an error that says that I can't access
from instance reference.
Is there a way to implement UnitTest without editing the production code?
[TestClass()]
public class LoggerTests
{
[TestMethod()]
public void DebugTest()
{
var mock = new Mock<Logger>();
mock.Setup(x => x.Debug(It.IsAny<string>());
new Logger(mock.Object).AddLog("testing");
mock.VerifyAll;
}
}
Program.cs
private static void ConfigureLogger()
{
Logger.AddLog(new NLogAppender());
Logger.Level = TraceLevel.Verbose;
Logger.Info("Configured Logger");
}
Logger.cs
public class Logger
{
public static readonly List<IAppender> loggings = new List<IAppender>();
public static void AddLog(IAppender appender)
{
loggings.Add(appender);
}
public static TraceLevel Level { get; set; }
static Logger()
{
Level = TraceLevel.Verbose;
}
public static void Info(string message)
{
LogMessage(message);
}
}
NlogAppender.cs
public class NLogAppender : IAppender
{
public NLog.Logger logger;
public NLogAppender()
{
logger = LogManager.GetLogger(nameof(NLogAppender));
}
public void AddLog(string str)
{
}
}
IAppender.cs
public interface IAppender
{
void AddLog(string str);
}
You can't mock a static class, and you shouldn't mock the class/system under test.
Add a mock appender to the logger:
// Arrange
var logString = "test-info"
var appenderMock = new Mock<IAppender>();
appenderMock.Setup(a => a.AddLog(logString));
Logger.AddLog(appenderMock.Object);
// Act
Logger.Info(logString);
// Assert
// TODO: exactly once
appenderMock.VerifyAll();
Note this static class may persist data between tests causing unexpected results, consult your test framework for configuring this.
Apart from that, you usually don't want to roll your own logging infrastructure, there's lots of things you can do wrong and why reinvent the wheel? Plenty of ILogger(<T>) implementations around.

Cannot unit test a class with a method returning RedisResult with StackExchange.Redis

I have a simple wrapper for stackexchange redis:
public interface IRedisClient
{
Task<RedisResult> ScriptEvaluate(LuaScript script, object parameters);
}
I have a method that calls ScriptEvaluate
public class Foo
{
private readonly IRedisClient _client;
public Foo(IRedisClient client)
{
_client = client;
}
public void RunScript()
{
_client.ScriptEvaluate(LuaScript.Prepare(""), new object());
}
}
Now when I use NSubstitute to mock IRedisClient that is injected to Foo and then call RunScript
public void Test()
{
_foo = new Foo(Substitute.For<IRedisClient>());
_foo.RunScript();
}
I get the following error:
System.TypeLoadException: Method 'AsBoolean' in type
'Castle.Proxies.RedisResultProxy' from assembly
'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=a621a9e7e5c32e69' does not have an implementation.
As far as I can see Nsubstitute/Castle internals do not manage to work with RedisResult properly. I did not manage to find out any workarounds.
Is it possible to do something with this?
P.S. I get the same error when I try to configure the mock to return a value (same exception):
_client
.ScriptEvaluate(null, null)
.ReturnsForAnyArgs(RedisResult.Create((RedisKey)"result"));
I was curious about why mocking the abstract RedisResult was not a simple solution.
This appears to be an issue with NSubstitute's implementation.
Using the following to try and recreate the problem
public class Foo {
private readonly IRedisClient _client;
public Foo(IRedisClient client) {
_client = client;
}
public Task<RedisResult> RunScript() {
return _client.ScriptEvaluate(LuaScript.Prepare(""), new object());
}
}
I was able to reproduce it using NSubstitute but was able to exercise the test to completion when using another mocking framework (MOQ)
[TestClass]
public class MyTestClass {
[TestMethod]
public async Task Test1() {
//Arrange
var expected = RedisResult.Create((RedisKey)"result");
var _client = Substitute.For<IRedisClient>();
_client
.ScriptEvaluate(Arg.Any<LuaScript>(), Arg.Any<object>())
.Returns(expected);
var _foo = new Foo(_client);
//Act
var actual = await _foo.RunScript();
//Assert
actual.Should().Be(expected);
}
[TestMethod]
public async Task Test2() {
//Arrange
var expected = RedisResult.Create((RedisKey)"result");
var _client = Mock.Of<IRedisClient>(_ => _.ScriptEvaluate(It.IsAny<LuaScript>(), It.IsAny<object>()) == Task.FromResult(expected));
var _foo = new Foo(_client);
//Act
var actual = await _foo.RunScript();
//Assert
actual.Should().Be(expected);
}
}
RedisResult is an abstract type, but there are static Create methods for common scenarios, and a few static properties such as EmptyArray, NullArray, etc. I can't tell you how to configure your particular faking layer, but ultimately, I'd expect something involving RedisResult.Create

Injection into Console Application with the Simple Injector

I am using Simple Injector for test purpose but pretty new on OOP. I am trying to create loosely couple classes. Here is the my scenario.
I have User repo and interface like this.
public class UserRepository : IUserRepository
{
public void Add(Model.User user)
{
Console.WriteLine("Name:"+user.Name+"\n"+"SurName:"+user.SurName);
}
public void Delete(int id)
{
throw new NotImplementedException();
}
}
public interface IUserRepository
{
void Add(User user);
void Delete(int id);
}
My TestInjectedClass Class and interface are something like this which I am planning to use in Program Main.
public class TestInjectedClass : ITestInjectedClass
{
private readonly IUserRepository _userRepository;
public TestInjectedClass(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public void UserRepoRun()
{
var user = new User() {Id = 1,Name = "ada",SurName = "stack"};
_userRepository.Add(user);
}
}
public interface ITestInjectedClass
{
void UserRepoRun();
}
And My console program looks like this:
class Program
{
static ITestInjectedClass _testInjectedClass;
private static IUserRepository _userRepository;
static void Main(string[] args)
{
_testInjectedClass= new TestInjectedClass(_userRepository);
_testInjectedClass.UserRepoRun();
Console.ReadLine();
}
public Program()
{
Bootstrap.Start();
}
}
BootStrap class here:
class Bootstrap
{
public static void Start()
{
var container = new Container();
// Register your types, for instance:
container.Register<IUserRepository, UserRepository>(Lifestyle.Singleton);
container.Register<ITestInjectedClass, TestInjectedClass>(Lifestyle.Singleton);
//container.Register<IUserRepository, TestInjectedClass>(Lifestyle.Singleton);
//container.Register<IUserContext, WinFormsUserContext>();
container.Register<TestInjectedClass>();
// Optionally verify the container.
container.Verify();
}
}
My problem when I run program, I am getting a value exception on the _userRepository inside TestInjectionClass.
How can I properly inject TestInjectionClass and UserRepository to Main Program. Thanks
You need to make Bootstrap.container available in Program.Main and then use it to create instances of classes instead of directly calling their constructors directly:
_testInjectedClass = Bootstrap.container.GetInstance<ITestInjectedClass>();
Of course you will need to expose it in Bootstrap for that to work:
class Bootstrap
{
public static Container container;
public static void Start()
{
container = new Container();
// Register your types, for instance:
container.Register<IUserRepository, UserRepository>(Lifestyle.Singleton);
container.Register<ITestInjectedClass, TestInjectedClass>(Lifestyle.Singleton);
//container.Register<IUserRepository, TestInjectedClass>(Lifestyle.Singleton);
//container.Register<IUserContext, WinFormsUserContext>();
container.Register<TestInjectedClass>();
// Optionally verify the container.
container.Verify();
}
}
And call Bootstrap.Start from Program.Main:
static void Main(string[] args)
{
Bootstrap.Start();
_testInjectedClass = Bootstrap.container.GetInstance<ITestInjectedClass>();
_testInjectedClass.UserRepoRun();
Console.ReadLine();
}
The problem is because you are calling your Bootstrap code in Program class instance constructor.
So, actually when you start your program the execution environment, is calling entry point method Main. And your instance constructor is never executed.
Try changing your entry point method Main and 'Bootstrap' class code:
static void Main(string[] args)
{
var container = new Container();
Bootstrap.Start(container);
_testInjectedClass = container.GetInstance<TestInjectedClass>();
_testInjectedClass.UserRepoRun();
Console.ReadLine();
}
class Bootstrap
{
public static void Start(Container container)
{
// Register your types, for instance:
container.Register<IUserRepository, UserRepository>(Lifestyle.Singleton);
container.Register<ITestInjectedClass, TestInjectedClass>(Lifestyle.Singleton);
container.Register<TestInjectedClass>();
// Optionally verify the container.
container.Verify();
}
}
Please use SimpleInjector
Sample please refer
http://www.c-sharpcorner.com/UploadFile/4d9083/dependency-injection-using-simple-injector/

Bug in Autofac MEF integration: Instantiates component when only querying for metadata

There appears to be a bug in how Autofac handles service instantiation when integrating with MEF
The following test show that MEF does not instantiate the services before it have to. (In this case, I'm only querying for metadata)
[TestMethod]
public void Mef_DoesNotInstantiateService_WhenOnlyQueryingForMetadata()
{
var aggregateCatalog = CreateMefCatalog();
var container = new CompositionContainer(aggregateCatalog, true);
var serviceConsumer = container.GetExportedValue<ServiceConsumer>();
serviceConsumer.Services.Any(x => x.Metadata.Name == "Service1").Should().BeTrue();
}
The following test is failing, since Autfac is trying to create an instance of Service1 - which throws an exception in the constructor.
[TestMethod]
public void Autofac_DoesNotInstantiateService_WhenOnlyQueryingForMetadata()
{
var aggregateCatalog = CreateMefCatalog();
var builder = new ContainerBuilder();
builder.RegisterComposablePartCatalog(aggregateCatalog);
var container = builder.Build();
//Next line will throw an exception. (Autofac is instantiating the service, but should not)
var serviceConsumer = container.Resolve<ServiceConsumer>();
//Note: This test will never get here..
serviceConsumer.Services.Any(x => x.Metadata.Name == "Service1").Should().BeTrue();
}
Other code required by the tests
static AggregateCatalog CreateMefCatalog()
{
return new AggregateCatalog(new List<ComposablePartCatalog>
{
new AssemblyCatalog(Assembly.GetExecutingAssembly())
});
}
[Export]
class ServiceConsumer
{
[ImportMany]
public IEnumerable<Lazy<IService, INameMetadata>> Services { get; set; }
}
public interface IService { }
[Export(typeof (IService))]
[ExportMetadata("Name", "Service1")]
public class Service1 : IService
{
public Service1()
{
throw new Exception("This service should never be created");
}
}
public interface INameMetadata
{
string Name { get; }
}
BTW: I'm using the currently stable versions: Autofac 3.5.2 and Autofac.Mef 3.0.3

why isn't TestInitialize getting called automatically?

I'm using Microsoft.VisualStudio.TestTools.UnitTesting; but the method I marked as [TestInitialize] isn't getting called before the test. I've never used this particular testing framework before but in every other framework there is always a way of registering a Setup and TearDown method that will auto run before and after every single test. Is this not the case with the visual studio testing tools unit testing framework?
[TestClass]
public class RepoTest
{
private const string TestConnectionString = #"Server=localhost\SQL2014EXPRESS64; Database=RepoTest; Trusted_Connection=True;";
private const string MasterConnectionString = #"Server=localhost\SQL2014EXPRESS64; Database=master; Trusted_Connection=True;";
[TestInitialize]
private void Initialize()
{
using(var connection = new SqlConnection(MasterConnectionString))
using(var command = new SqlCommand(Resources.Initialize, connection))
{
command.ExecuteNonQuery();
}
}
[TestCleanup]
private void Cleanup()
{
using (var connection = new SqlConnection(MasterConnectionString))
using (var command = new SqlCommand(Resources.Cleanup, connection))
{
command.ExecuteNonQuery();
}
}
[TestMethod]
public void CreateARepo()
{
var repo = new Repo(TestConnectionString);
}
}
Make Initialize and Cleanup public. You can also check, that at msdn all examples have public accessor.
In order to reproduce, make such test class:
[TestClass]
public class Tests
{
[TestInitialize]
public void Initialize()
{
Console.WriteLine("initialize");
}
[TestCleanup]
public void Cleanup()
{
Console.WriteLine("cleanup");
}
[TestMethod]
public void Test()
{
Console.WriteLine("test body");
}
}
That test will produce the following results:
Making Initialize and Cleanup private, you'll see only test body being printed to the console:
Used Microsoft.VisualStudio.QualityTools.UnitTestFramework assembly as unit testing framework version 10.1.0.0 and ReSharper 8.2 as a test runner.

Categories