Unit testing QueueRuntimeInfo - c#

I'm trying to write unit tests around Microsoft.Azure.ServiceBus and need to return a mock instance of Microsoft.Azure.ServiceBus.Management.QueueRuntimeInfo in my tests. QueueRuntimeInfo has an internal constructor which takes a string as a parameter. So any attempt with Moq or in code to instantiate gets QueueRuntimeInfo does not contain a constructor that takes 0 arguments. Cannot access internal constructor of QueueRuntimeInfo here.
Read numerous articles including: http://www.blackwasp.co.uk/MoqInternals.aspx and http://www.blackwasp.co.uk/CSharpFriendAssembly.aspx
But not sure if this the correct way to go and being honest not 100% sure of how to put/reference InternalsVisibleTo in my unit test which is in a .net core 2.2 solution.
Is it possible to be able to create an instance of this in my unit tests please?

Related

Unit test a singleton class with MSTest

I want to test my class EventTextsDB that is a singleton, using MSTest in .NET 6.
I first thought about using AppDomain, but they basically were removed in .NET 5+ (https://learn.microsoft.com/en-us/dotnet/core/porting/net-framework-tech-unavailable#application-domains)
Then I found Unit test singletons, but by calling the private constructor via reflection I still cannot test the static Create() and static Delete() methods in the class, because they set the static EventTextsDB Instance property.
I could use ordered unit tests, but this would require a lot of work because I would have to order all tests that used this class. Not many tests use or test this class yet, but many do with a similar class LanguageDB, at which I want to apply the same solution that I am looking for.
I have read somewhere on stackoverflow or MSDN, that each test assembly runs isolated (in different AppDomain, if they still exist?), but I don't want to create 10 new test assemblies just for 10 tests of this class.
How can I test my singleton class?

How to mock away Process.GetProcessesByName() call in a method I want to test?

I am writing a unit tests using Xunit and moq. Within one function it calls Process.GetProcessesByName(). I need this to return a process with a certain pid which would exist when my program is actually running. However since in the test this process won't exist how do I mock away this call to return a fake process I want so I can continue to test the rest of the method?
You will need to wrap the call to Process.GetProcessesByName() in an injectable class in order to mock it. There is no way for Moq to replace behaviour of static methods.
There's a good answer on this topic here: How to mock static methods in c# using MOQ framework?
What you might be trying is a system testing/Integration testing. Trying to get actual value during unit testing is not what Unit testing is meant to do. The scope of unit testing is to validate the functionality of the piece of code not on the data. If you are interested in testing the actual data, try other testing methods like automation testing.

Why are my unit tests using Moq's Verify() non-deterministic?

We are using Moq 4 for our unit tests, specifically controller unit tests. We are using Moq's Verify() method to make sure an error was logged. The problem is the tests can pass but then fail the very next run.
We are using Serilog for our logger.
The Action method looks like
public IActionResult Index(){
try{
var data = _repository.GetData();
return View(data);
}catch(Exception e){
Log.Error(e.Message);
}
}
So the unit test is using
_mockLogger.Verify(x=> x.Write(LogEventLevel.Error,It.IsAny<string>()));
mockLogger is setup in the test's constructor like
var _mockLogger = new Mock<Serilog.ILogger>();
Log.Logger = _mockLogger.Object;
//...
and the repository is mocked to throw an exception when invoked.
When it fails, we are getting the error message
"Moq.MoqException expected invocation on the Mock at least once but was never peformed x=>x.Write(LogEventLevel.Error,It.IsAny<string>())"
Any Ideas?
It's not entirely possible to see what the problem is from the posted code. And I appreciate how hard it can be to make a MCVE for this. So I'm going to take two guesses.
Guess 1: I suspect the cause of your issue is the use of statics in your code, specifically to do with the logger.
I suspect what's happening is that other tests (not shown in the post) are also modifying/defining how the logger should behave, and since the logger is static, the tests are interfering with each other.
Try redesigning the code so that the instance of the logging functionality is dependency injected into the class under test, using serilog's ILogger interface, store this in a readonly field and use that when you want to log.
Guess 2: Based on the part of the post which says "...setup in the test's constructor" you haven't said (or tagged) which testing framework you're using; but the handful that I've used prefer you to do this kind of thing in attributed methods rather than in the constructor of the test. For example, NUnit has OneTimeSetUp (before any of the tests in that class are run), SetUp (before each test in that class is run), TearDown (after each test in that class is run), OneTimeTearDown (after all of the tests in that class are run). It's possible that the constructors of your tests are being called in an order that you're not expecting, and which is not supported by your testing framework; whereas the attributed methods sequence is guaranteed by the framework.

How to execute XUnit tests via code

I have tests written in XUnit using InlineData and MemberData attributes. I would like to run tests via code elsewhere in my project and have the attributes automatically fill in test data like they normally do when ran through the VS test runner.
If it weren't for the attributes I would just call the methods directly like any other normal method. The asserts are still checked and it functions fine. But if I call a method directly that has the attributes, the attributes are ignored and I must provide all the test data manually through code. Is there some sort of test runner class in XUnit that I can reuse to accomplish this? I've been trying to dig through their API to no avail.
Why I want to do this will take some explanation, but bear with me. I'm writing tests against specific interfaces rather than their concrete implementations (think standard collection interfaces for example). There's plenty there to test and I don't want to copy paste them for each concrete implementer (could be dozens). I write the tests once and then pass each concrete implementation of the interface as the first argument to the test, a subject to test on.
But this leaves a problem. XUnit sees the test and wants to run it, but it can't because there are no concrete implementations available at this layer, there's only the interface. So I want to write tests at the higher layer that just new up the concrete implementations, and then invoke the interface tests passing in the new subjects. I can easily do this for tests that only accept 1 argument, the subject, but for tests where I'm using InlineData or MemberData too I would like to reuse those test cases already provided and just add the subject as the first argument.
Available for reference is the GitHub issue How to programmatically run XUnit tests from the xUnit.net project.
The class AssemblyRunner is now part of Xunit.Runner.Utility.
From the linked issue, xUnit.net contributor Brad Wilson provided a sample runner in the samples.xunit project on GitHub. This program demonstrates the techniques described in the issue. Namely, the portion responsible for running the tests after they have been discovered is as follows:
using (var runner = AssemblyRunner.WithAppDomain(testAssembly))
{
runner.OnDiscoveryComplete = OnDiscoveryComplete;
runner.OnExecutionComplete = OnExecutionComplete;
runner.OnTestFailed = OnTestFailed;
runner.OnTestSkipped = OnTestSkipped;
Console.WriteLine("Discovering...");
runner.Start(typeName);
finished.WaitOne(); // A ManualResetEvent
finished.Dispose();
return result;
}
For a deeper dive, he describes a method using XunitFrontController and TestDiscoveryVisitor to find and run tests. This is what AssemblyRunner does for its implementation.
Nevermind, I figured it out. Taking a closer look at XUnit's attribute hierarchy I found that the DataAttributes (InlineData, MemberData, etc) have a GetData method you can call to retrieve the set of data they represent. With a little reflection I can easily find all the tests in my test class and call the test methods, invoking the data attribute's get data method if there are any present, and perform the tests via my own code that way. The GetData part would have been much harder if I had to role my own version of it. Thank you XUnit authors for not forcing me to do that.

Using TestContext to share information between unit tests

I'm writing a set of unit tests to test a CRUD system.
I need to register a user in Test1 - which returns a ServiceKey
I then need to add data in Test2 for which I need the ServiceKey
What is the best way to pass the ServiceKey? I tried to set it in the TestContext, but it just seems to disappear between the tests.
You should not share aany state between unit tests, one of the very important properties of good unit tests - Independency. Tests should not affect each other.
See this StackOverflow post: What Makes a Good Unit Test?
EDIT: Answer to comment
To share a logic/behaviour (method) you can extract the common code into a helper method and call it from different tests, for instance helper method which creates an user mock:
private IUser CreateUser(string userName)
{
var userMock = MockRepository.GenerateMock<IUser>();
userMock.Expect(x => x.UserName).Return(userName);
return userMock;
}
the idea of unit tests is that each tests checks one functionality. if you create dependencies in between your tests it is no longer certain that they will pass all the time (they might get executed in a different order, etc.).
what you can do in your specific case is keeping your Test1 as it is. it only focuses on the functionality of the registering process. you don't have to save that ServiceKey anywhere. just assert inside the test method.
for the second test you have to setup (fake) everything you need it to run successfully. it is generally a good idea to follow the "Arrange Act Assert"-Principle, where you setup your data to test, act upon it and then check if everything worked as intended (it also adds more clarity and structure to your tests).
therefore it is best to fake the ServiceKey you would get in the first test run. this way it is also much easier to controll the data you want to test. use a mocking framework (e.g. moq or fakes in vs2012) to arrange your data they way you need it. moq is a very lightweight framework for mocking. you should check it out if you are yet not using any mocking utilities.
hope this helps.

Categories

Resources