Unit Testing quartz-dot-net (Quartz.Net) Execute function - c#

I would like to test the Execution function of my Quartz.Net jobs, which implement the Quartz.IJob:
public void Execute(IJobExecutionContext context)
The problem: how to create a new IJobExecutionContext class instance. Or even instead of creating a New one, just get it from an already existing scheduled job.
The goal is to create a test such as:
[Test()]
public void Test()
{
IJobExecutionContext jobExecutionContext = ???; //get a defined JobExecutionContext somehow...
m_myJob.Execute(jobExecutionContext);
}
All I have found has been this related post with the same problem. All he said was "Solved by passing only JobDataMap object to my method: context.MergedJobDataMap" which I don't seem to be able to reproduce. And the other proposition, the use of Moq, is out of reach for me at this current time. Although if it really is the only way, I will focus on this solution. But I thought it was reasonable if I tried to find a simpler way first.

IJobExecutionContext is an interface, which means you can create a mock version of it easily. Either by using a Mocking framework, like Moq as you mentioned, or by creating a class just for use in your test
private class MockExecutionContext : IJobExecutionContext
{
}
you will need to implement all the members of the interface, and give them the behaviour which your test needs, but the compiler/intellisense will help you with this. Depending on what you are testing, you should be able to give most of the members 'stub' implementations that do nothing other than satisfy the member signatures.

Related

C# how to "register" class "plug-ins" into a service class?

Update#2 as of year 2022
All these years have passed and still no good answer.
Decided to revive this question.
I'm trying to implement something like the idea I'm trying to show with the following diagram (end of the question).
Everything is coded from the abstract class Base till the DoSomething classes.
My "Service" needs to provide to the consumer "actions" of the type "DoSomethings" that the service has "registered", at this point I am seeing my self as repeating (copy/paste) the following logic on the service class:
public async Task<Obj1<XXXX>> DoSomething1(....params....)
{
var action = new DoSomething1(contructParams);
return await action.Go(....params....);
}
I would like to know if there is anyway in C# to "register" all the "DoSomething" I want in a different way? Something more dynamic and less "copy/paste" and at the same time provide me the "intellisense" in my consumer class? Somekind of "injecting" a list of accepted "DoSomething" for that service.
Update#1
After reading the sugestion that PanagiotisKanavos said about MEF and checking other options of IoC, I was not able to find exactly what I am looking for.
My objective is to have my Service1 class (and all similar ones) to behave like a DynamicObject but where the accepted methods are defined on its own constructor (where I specify exactly which DoSomethingX I am offering as a method call.
Example:
I have several actions (DoSomethingX) as "BuyCar", "SellCar", "ChangeOil", "StartEngine", etc....
Now, I want to create a service "CarService" that only should offer the actions "StartEngine" and "SellCar", while I might have other "Services" with other combination of "actions". I want to define this logic inside the constructor of each service. Then, in the consumer class, I just want to do something like:
var myCarService = new CarService(...paramsX...);
var res1 = myCarService.StartEngine(...paramsY...);
var res2 = myCarService.SellCar(...paramsZ...);
And I want to offer intellisense when I use the "CarService"....
In conclusion: The objective is how to "register" in each Service which methods are provided by him, by giving a list of "DoSomethingX", and automatically offer them as a "method"... I hope I was able to explain my objective/wish.
In other words: I just want to be able to say that my class Service1 is "offering" the actions DoSomething1, DoSomething2 and DoSomething3, but with the minimum lines as possible. Somehow the concept of the use of class attributes, where I could do something similar to this:
// THEORETICAL CODE
[RegisterAction(typeOf(DoSomething1))]
[RegisterAction(typeOf(DoSomething2))]
[RegisterAction(typeOf(DoSomething3))]
public class Service1{
// NO NEED OF EXTRA LINES....
}
For me, MEF/MAF are really something you might do last in a problem like this. First step is to work out your design. I would do the following:
Implement the decorator design pattern (or a similar structural pattern of your choice). I pick decorator as that looks like what you are going for by suplimenting certain classes with shared functionality that isn't defined in those clases (ie composition seems prefered in your example as opposed to inheritance). See here http://www.dofactory.com/net/decorator-design-pattern
Validate step 1 POC to work out if it would do what you want if it was added as a separate dll (ie by making a different CSProj baked in at build time).
Evaluate whether MEF or MAF is for right for you (depending on how heavy weight you want to go). Compare those against other techniques like microservices (which would philosophically change your current approach).
Implement your choice of hot swapping (MEF is probably the most logical based on the info you have provided).
You could use Reflection.
In class Service1 define a list of BaseAction types that you want to provide:
List<Type> providedActions = new List<Type>();
providedActions.Add(typeof(DoSomething1));
providedActions.Add(typeof(DoSomething2));
Then you can write a single DoSomething method which selects the correct BaseAction at run-time:
public async Task<Obj1<XXXX>> DoSomething(string actionName, ....params....)
{
Type t = providedActions.Find(x => x.Name == actionName);
if (t != null)
{
var action = (BaseAction)Activator.CreateInstance(t);
return await action.Go(....params....);
}
else
return null;
}
The drawback is that the Client doesn't know the actions provided by the service unless you don't implement an ad-hoc method like:
public List<string> ProvidedActions()
{
List<string> lst = new List<string>();
foreach(Type t in providedActions)
lst.Add(t.Name);
return lst;
}
Maybe RealProxy can help you? If you create ICarService interface which inherits IAction1 and IAction2, you can then create a proxy object which will:
Find all the interfaces ICarService inherits.
Finds realizations of these interfaces (using actions factory or reflection).
Creates action list for the service.
In Invoke method will delegate the call to one of the actions.
This way you will have intellisence as you want, and actions will be building blocks for the services. Some kind of multi-inheritance hack :)
At this point I am really tempted to do the following:
Make my own Class Attribute RegisterAction (just like I wrote on my "Theoretical" example)
Extend the Visual Studio Build Process
Then on my public class LazyProgrammerSolutionTask: Microsoft.Build.Utilities.Task try to find the service classes and identify the RegisterAction attributes.
Then per each one, I will inject using reflection my own method (the one that I am always copying paste)... and of course get the "signature" from the corresponding target "action" class.
In the end, compile everything again.
Then my "next project" that will consume this project (library) will have the intellisence that I am looking for....
One thing, that I am really not sure, it how the "debug" would work on this....
Since this is also still a theoretically (BUT POSSIBLE) solution, I do not have yet a source code to share.
Meanwhile, I will leave this question open for other possible approaches.
I must disclose, I've never attempted anything of sorts so this is a thought experiment. A couple of wild ideas I'd explore here.
extension methods
You could declare and implement all your actions as extension methods against base class. This I believe will cover your intellisense requirements. Then you have each implementation check if it's registered against calling type before proceeding (use attributes, interface hierarchy or other means you prefer). This will get a bit noisy in intellisense as every method will be displayed on base class. And this is where you can potentially opt to filter it down by custom intellisense plugin to filter the list.
custom intellisense plugin
You could write a plugin that would scan current code base (see Roslyn), analyze your current service method registrations (by means of attributes, interfaces or whatever you prefer) and build a list of autocomplete methods that apply in this particular case.
This way you don't have to install any special plugins into your Dev environment and still have everything functional. Custom VS plugin will be there purely for convenience.
If you have a set of actions in your project that you want to invoke, maybe you could look at it from CQS (Command Query Separation) perspective, where you can define a command and a handler from that command that actually performs the action. Then you can use a dispatcher to dispatch a command to a handler in a dynamic way. The code may look similar to:
public class StartEngine
{
public StartEngine(...params...)
{
}
}
public class StartEngineHandler : ICommandHandler<StartEngine>
{
public StartEngineHandler(...params...)
{
}
public async Task Handle(StartEngine command)
{
// Start engine logic
}
}
public class CommandDispatcher : ICommandDispatcher
{
private readonly Container container;
public CommandDispatcher(Container container) => this.container = container;
public async Task Dispatch<T>(T command) =>
await container.GetInstance<ICommandHandler<T>>().Handle(command);
}
// Client code
await dispatcher.Dispatch(new StartEngine(params, to, start, engine));
This two articles will give you more context on the approach: Meanwhile... on the command side of my architecture, Meanwhile... on the query side of my architecture.
There is also a MediatR library that solves similar task that you may want to check.
If the approaches from above does not fit the need and you want to "dynamically" inject actions into your services, Fody can be a good way to implement it. It instruments the assembly during the build after the IL is generated. So you could implement your own weaver to generate methods in the class decorated with your RegisterAction attribute.

How do I Moq IFindFluent so this call to ToListAsync works?

I am unit testing a wrapper to the MongoDB C# driver. I have this line of code:
Collection.Find(predicate).ToListAsync();
Where Collection is of type IMongoCollection<T> and Find(predicate) returns an instance implementing IFindFluent<T, T>. ToListAsync() is an extension to turn the results into a list, I assume.
I am attempting to write unit tests, and I am stumped on handling this. I can't make a wrapper class because that's what I'm working on. I would prefer to either make it so ToListAsync() returns a created list OR to mock the Find() to return something that can be made a list of.
If anyone would struggle with getting it to work, what I did to mock Find() method was:
[TestFixture]
class QueryControllerTests
{
private IOptions<MongoSettings> _mongoSettings;
private QueryController _queryController;
private Mock<IFakeMongoCollection> _fakeMongoCollection;
private Mock<IFindFluent<BsonDocument, BsonDocument>> _fakeCollectionResult;
[OneTimeSetUp]
public void Setup()
{
_fakeMongoCollection = new Mock<IFakeMongoCollection>();
_fakeCollectionResult = new Mock<IFindFluent<BsonDocument, BsonDocument>>();
}
}
where IFakeMongoCollection is:
public interface IFakeMongoCollection : IMongoCollection<BsonDocument>
{
IFindFluent<BsonDocument, BsonDocument> Find(FilterDefinition<BsonDocument> filter, FindOptions options);
}
I wound up making a little abstraction layer for this, since I couldn't find anything suitable and asking for help yielded no answers.
I created an interface/implementation pair called AppCollection specifically to handle the MongoDB interface. IAppCollection would have a method for IAppCollection.ToList(predicate), and the AppCollection would run the Collection.Find(predicate).ToListAsync(); call, returning the list. Later, it was a trivial matter to mock the IAppCollection to make sure the right calls were being made. While I couldn't test the predicates in native LINQ, I could at least compile the predicates and compare them to passing/failing objects.

How to test methods where DBContext is created?

I don't have a lot of experience with unit testing. For example I have simple method in the application:
public void GetName()
{
UserRights rights = new UserRights(new DatabaseContext());
string test = rights.LookupNameByID("12345");
Console.WriteLine(test);
}
In this case I'm able to test all methods of UserRights class by passing mocked DatabaseContext, but how can I test GetName() method? What is the best practice? Where DatabaseContext should be created?
If you want to test the GetName method in a properly isolated way (i.e. a Unit Test) then you can't use new to create the UserRights instance in the method itself; because a test is really just another client of the code, therefore it can't (and shouldn't) know anything about how GetName works internally
So what this means is that for a proper Unit Test you must be able to replace all dependencies of a method with ones that the client fully controls - in the case, the code in the Unit Test is the client.
In your posted code, the client code has no control at all over UserRights nor DatabaseContext, so this is the first thing that has to change.
You need to rework your code so that the UserRights implementation can be supplied by the client. In fact once that's done, the problem about where DatabaseContext comes from is actually irrelevant for the Unit test because it doesn't care about how UserRights itself performs its tasks!
There are a number of ways of doing this; you can use Mocks or Stubs, you can use Constructor or Method injection, you could use a UserRights factory. Here is an example of using very simple stubs which IMHO is the best way to start and avoids having to learn a Mocking framework -- I personally would use Mocks for this but that's cos I am lazy :)
(code below assumes the class containing GetName is called "UserService", and uses xUnit framework; but MSTest will work just fine too)
Let's suppose you have control over the code of UserService so you can make the LookupNameByID method virtual (if you can't, then you may have to go the route if interfaces and mocks)
public class UserRights
{
public virtual LookupNameByID(string id)
{
//does whatever a UserRights does.
}
}
public class UserService
{
readonly UserRights _rights;
public UserService(UserRights rights)
{
_rights=rights; //null guard omitted for brevity
}
public string GetName(string id)
{
return _rights.LookupNameByID(id);
}
}
now in your unit test code suppose you create a sub-class of UserRights like this:
public class ExplodingUserRights: UserRights
{
public override string LookupNameByID(string id)
{
throw new Exception("BOOM!");
}
}
Now you can write a test to see how GetName reacts when something bad happens:
[Fact]
public void LookupNameByID_WhenUserRightsThrowsException_DoesNotReThrow()
{
//this test will fail if an exception is thrown, thus proving that GetName doesn't handle exceptions correctly.
var sut = new UserService(new ExplodingUserRights()); <-Look, no DatabaseContext!
sut.GetName("12345");
}
and one for when good things happen:
public class HappyUserRights: UserRights
{
public override string LookupNameByID(string id)
{
return "yay!";
}
}
[Fact]
public void LookupNameByID_ReturnsResultOfUserRightsCall()
{
//this test will fail if an exception is thrown, thus proving that GetName doesn't handle exceptions correctly.
var sut = new UserService(new HappyUserRights());
var actual = sut.GetName("12345");
Assert.Equal("yay!",actual);
}
and so on. Note that we never went anywhere near DatabaseContext, because that's a problem you only have to solve when you unit test the UserRights class itself. (and at that point I would probably recommend using Jeroen's advice from his linked article,and do an integration test, unless setup of a database for each test is something you can't or won't do, in which case you need to use interfaces and mocks)
Hope that helps.
Separating your codes reliance on DB Context is something you will want to investigate, this can be accomplished using the Repository pattern. Since you're passing the DB Context into your objects constructor, in this case UserRights, you can pretty easily change your code to take in an Interface (or simply add an overloaded contructor to the class that accepts an interface, then call that in your unit tests, preserving any existing code). There are lots of ways to get this done, a quick Google search yielded the following article:
http://romiller.com/2012/02/14/testing-with-a-fake-dbcontext/
http://www.codeproject.com/Articles/207820/The-Repository-Pattern-with-EF-code-first-Dependen
Once your class can accept an interface rather than (or as an alternative to) the strongly typed DB Context object you can use a Mock framework to assist with testing. Take a look at Moq for examples on how to use these in your unit tests https://github.com/Moq/moq4/wiki/Quickstart
Be Aware: Moq can become difficult to work with when your tests require data that is related via foreign keys, the syntax can be complicated to get your head around. One thing to watch out for is the temptation to make changes to your code just to make a unit test easier to set up, while there may be value in making this change it also may indicate that you need to re-think your unit test rather than violate your applications architecture and/or design patterns

Can I share the same setup across multiple mocks of the same type?

As the title says, can I make a Setup for one Mock and then somehow transfer it across multiple objects of the same type?
Let's say I am creating a Mock<IProcessor>(). I want to create multiple of these mock objects, but with the same setup (ie, all should have the same expectations, but there are several instances of them). It wouldn't make much sense for me to repeat the code multiple times - can I share the ISetup somehow?
Moq itself doesn't provide a facility for that, AFAIK.
But you can easily move your setup code to an extension method:
public static void MySetup(this Mock<IProcessor> mock)
{
mock.<setup-whatever>
}
Then, in each location where you need it, you can do this:
...
var mock = new Mock<IProcessor>();
mock.MySetup();
...

How can I use Rhino mocks to mock just one value in a test object?

Been making some changes to our code, and now I need to re-factor some unit tests to make sure they're compatible with the new code. I've come up against a problem. In this:
ChannelLoad loader = new ChannelLoad(_customerDbMock, _bulkCopyMock);
loader.Execute(taskId);
The "loader" object is now trying to connect to another object in order to get a string value whereas before the string was returned automatically. So the obvious solution is to mock that object to return a suitable value for the test. However for various reasons I can't easily do this.
Ideally what I'd like to be able to do is to get a "real" (i.e as specified in code) loader object that performs a "real" Execute method but which has a "mock" value for that particular string. But I'm really not sure how to do this - even if it's possible - with Rhino Mocks. The string property in question isn't abstract or anything - it's protected and it's actually read-only. This is how it looks inside "loader":
protected string DbConnectionString
{
get
{
return _Service.GetLocalDatabase().GetConnectionString(_Service);
}
}
And the problem is that for the test environment "GetLocalDatabase" returns nothing.
Anyone help me out here? Is there a way I can mock this up using Rhino Mocks or is my only option to refactor the code to make it not rely on an external object? If the latter, pointers would also be helpful.
Cheers,
Matt
Two other options if you don't want to inject _Service:
Create a class that inherits from ChannelLoad (call it "TestableChannelLoader" or something) and
overwrite the DbConnectionString-Property or
extract a method "GetConnectionString" that you can override in your new class and call it in the DbConnectionString-Property
I see that loader has dependency to _Service. So, you need to inject mock of this dependency to loader in order to change DbConnectionString property behavior.

Categories

Resources