Unit Test & Log4net - asp.net

I have unit test testing an action in my controller, the action writes to log4net.
When I run my action it works well - writes to log4net .
However , When I run the unit test - the action doesn't write to log4net but doesn't throw any exception.
Does anyone have a solution?

// ARRANGE
var memoryAppender = new MemoryAppender();
BasicConfigurator.Configure(memoryAppender);
// ACT
_sut.DoWhatever();
// ASSERT - using xunit - change the expression to fit your purposes
Assert.True(memoryAppender.GetEvents().Any(le => le.Level == Level.Warn), "Expected warning messages in the logs");
You don't need to add in another layer of indirection by using a logging interface (if you don't want to). I have used the abstracted way for years, but now am moving towards just using the MemoryAppender as it is testing what is actually happening. Just be sure to .Clear() the appender after each test.

Log4net does not throw exceptions: http://logging.apache.org/log4net/release/faq.html
Writing to an log on disk or in a database in a unit test is counterproductive; the whole point is automation. You shouldn't have to check the logs every time you run tests.
If you truly need to verify that a call was made to log something, you should mock the ILog interface and assert that the appropriate method was called.
If you are using a mocking framework, this is trivial. If you aren't, you can create a TestLogger class that implements or partially implements ILog and exposes extra properties that show how many times a given method was called. Your assertions will check that the methods were called as expected.
Here is an example of a class to be tested:
public class MyComponent
{
private readonly ILog _log;
public MyComponent(ILog log)
{
_log = log;
}
public string DoSomething(int arg)
{
_log.InfoFormat("Argument was [{0}]", arg);
return arg.ToString();
}
}
and the test (using Rhino.Mocks to mock the ILog):
[TestClass]
public class MyComponentTests
{
[TestMethod]
public void DoSomethingTest()
{
var logger = MockRepository.GenerateStub<ILog>();
var component = new MyComponent(logger);
var result = component.DoSomething(8);
Assert.AreEqual("8", result);
logger.AssertWasCalled(l => l.InfoFormat(Arg<string>.Is.Anything, Arg<int>.Is.Equal(8)));
}
}

Try adding:
[assembly: log4net.Config.XmlConfigurator()]
To the AssemblyInfo.cs (or init log4net any other way).
Or try using AssemblyInitialize as suggested in this answer.

It is your log4net configuration. Right now it might be in your web.config or log4net.config file in the web/bin. You have to place it in a common location and make it discoverable by both web app and test. Or you have to put it into your unittest.project=>app.config file. But if you have many test projects, it would be duplicated in number of places. So the ideal would be to put it in a common place.

Here's another possible solution if none of the other solutions work for you...
Try writing your log file to the root of the c drive. By default, I set log4net to write to the current directory which is always the directory the unit test is running from right?... wrong! I'm running windows 8 with vs 2012 using MS Unit Test, and it writes the file to a local temp directory which gets deleted after the unit test completes. In my setup it writes the file to here:
C:\Users\[myself]\AppData\Local\Temp\TestResults
Bottom line, any unit tests I write for now on, are going to use a full absolute log file path and not a relative one.

Related

Grails 3.3 Multiple Asynchronous GORM calls during integration test without access to the database.

I was writing integration tests in Grails 3.3 with multiple Asynchronous GORM calls when I realized I could not get access to values stored in the database. I wrote the following test to understand what is happening.
void "test something"() {
given:
def instance = new ExampleDomain(aStringField: "testval").save(flush:true)
when:
def promise = ExampleDomain.async.task {
ExampleDomain.get(instance.id).aStringField
}
then:
promise.get() == "testval"
}
My domain class
class ExampleDomain implements AsyncEntity<ExampleDomain> {
String aStringField
static constraints = {}
}
build.gradle configuration
compile "org.grails:grails-datastore-gorm-async:6.1.6.RELEASE"
Any idea what is going wrong? I'm expecting to have access to the datastore during the execution of the async call.
Most likely the given block is in a transaction that hasn't committed. Without seeing the full test class it is impossible to know, however it is likely you have the #Rollback annotation.
The fix is to remove the annotation and put the logic for saving the domain in a separate transactional method. You will then be responsible for cleaning up any inserted data.

Autofac SingleInstance() and Xamarin Forms

To start, let me say that I have read several questions here about SingleInstance, but still cannot find a direct answer that helps me. That said, I apologize if I missed anything.
Here's my question:
I am building a Xamarin Forms app for iOS and Android. I have a single AppInitializer class in a PCL where I register all of my interface dependencies using Autofac. I then assign the Container from the builder as a static property on the app class. The problem I encounter is that while I'm registering everything with .SingleInstance(), I'm not actually getting a single instance.
Init Logic Example:
var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
I am letting Autofac handle resolving interfaces in my constructors. For example:
public MemberViewModel(ISettingsViewModel settings, IErrorHandler errorHandler, …) : base(settings, errorHandler){…}
I then use said model on a page as below:
Example page usage:
public ProfilePage()
{
InitializeComponent();
var displayModel = Model.CurrentMember;
…
}
…
**public IMemberViewModel Model =>
AppContainer.Current.Resolve<IMemberViewModel>();**
In this example I set Model.CurrentMember's properties immediately before arriving on this page. I've set breakpoints and know for a fact this is happening. However, when I resolve the instance of the model, the properties on CurrentMember are null.
Am I doing something wrong here or have I encountered a bug?
-Edit-
Made it clear that I'm using Autofac.
-Edit 2-
Adding more detail.
My implementation of the IMemberViewModel class has various properties on it, including an observable object called current member. It is declared as below:
public class MemberViewModel : ViewModelBase, IMemberViewModel
{
…
(see constructor above)
…
public MemberDisplay CurrentMember =>
m_CurrentMember ?? (m_CurrentMember = new MemberDisplay())
On the implementation of IMemberViewModel I have a method that sets the various properties on CurrentMember.
The order of operations is this:
The end user taps an image for a member. This fires a command on the (theoretically) singleton instance of the IMemberViewModel implementation. This command executes an async task that awaits an async call to the API to load the data for that member. After that data is loaded and the properties set on CurrentMember, the app navigates to the profile screen. The profile screen resolves IMemberViewModel (per above).
Expected Behavior:
The properties on CurrentMember from the resolved instance of IMemberViewModel are set to the values that have just been set from the load data method. This expectation arises from assuming that there is a single instance of IMemberViewModel.
Actual Behavior:
The CurrentMember's properties are at their default values, i.e. string.Empty, 0, null, etc.
The odd thing here is that this doesn't happen to every model. I have a message model that I am resolving in the same manner on the same screen and it seems to be fine.
This issue turned out to be caused by the way we were going about initializing everything. For posterity's sake, I will give a brief breakdown of what was happening and what I did to prevent it.
Previous App Flow:
App opens & constructor is called. This calls into the initialization routine above.
User logs in.
First instance of IMemberViewModel resolved using static container.
A message pops up asking the user for Push Notifications Permissions
When this happens, the app OnSleep is called (iOS)
After the user selects an answer, OnResume is called.
OnResume calls initialization routine
New container created.
Call to load data happens on old container, new pages reference new container.
Issue arises as described above.
Correction to the flow:
First, from what I can tell the init calls do not need to be made on resume and/or start if made in the app constructor. If the app is "killed" because other apps need the memory space, a fresh version of the app will be created on next launch (see the Android Activity Lifecycle and the iOS App Lifecycle).
Second, because I'm paranoid and because it can't hurt, in the app init routine I am now checking to determine whether the container exists and whether the interface is already registered.
public static void Init(ISetup setup)
{
if (Container != null && IsModelRegistered()) return;
RegisterDependencies(setup);
…
}
private static bool IsModelRegistered()
{
return Container.IsRegistered<IMemberViewModel>();
}

warning: "Cannot find file '/3' locally. To fix it set server name by environment variable PHP_IDE_CONFIG and restart debug session."

Every time I step into the method (prepareStatusFilterQuery()) while unit testing with debug I got warning and debugger not stepping into the method. Warning:
Cannot find file '/3' locally. To fix it set server name by
environment variable PHP_IDE_CONFIG and restart debug session.
Other than this case debugger works fine.
This happens when you try to step into the code of a mock object.
There is no solution for it because the mock objects are instances of classes that are created during the execution of the test.
PHPUnit MockObjects uses reflection to gather information about the class you ask it to mock (the names and arguments of the public methods) then it generates the PHP code of a new class (that extends the mocked class) and runs it using eval().
The debugger is actually stepping into the method but PhpStorm cannot display the source code because there is no source code for it. Keep using the "Step Into" command and at some point the control will go back to code (of PHPUnit) whose source code is loaded from a file and PhpStorm can find it.
Just encountered this error. In my case it was caused by the method missing the private keyword:
class SomeClass {
function some_function_name () {
}
}
Should look like:
class SomeClass {
private function some_function_name () {
}
}

Microsoft Fakes - Stubbing an Extension Method Shouldn't Work But It Does

I have an interface, ILoader, on which I have defined an extension method CheckLoaderDatabaseConnection:
//the extension method
public static class LoaderExtensions
{
public static void CheckLoaderDatabaseConnection(this ILoader loader)
{
//data access stuff
}
All the doumentation out there tells me I have to use shims when I want to stub an extension method because the method is static and it can't be stubbed.
True, it doesn't work in Moq because I've tried it.
But I can stub the interface in Fakes:
var loader = new MyNamespace.Fakes.StubILoader() { };
In my unit test, I pass in the stub to the constructor of the concrete instance I'm testing and when it gets to this line:
loader.CheckLoaderDatabaseConnection();
It calls the stubbed method (which does nothing) and works ok.
Why is this? I must be missing something. I haven't had to use shims here at all (though I can't stub it in Moq - when I try that, the real world extension is called & the whole thing blows up)
No, the extension method wasn't getting invoked but after rebooting from a blue screen of death earlier the extension method is now getting invoked and the unit test is failing as I would expect.
Don't understand how this was working for several days though; something weird & I don't think this question can be answered.

How to remove trace command from Flex 3

I want to remove trace commands while creating the compiled SWF file and while goggling I come to know that Setting Omit Trace Actions to 'true' will fulfill this requirement but when I am using this key value pair in configuration file it is giving compilation error, so what can be the reason and how to resolve this issue.
Kindly note I am using version 3 of Flex.
To get around this, I use a custom Trace class:
public class Trace {
public static var shouldTrace:Boolean = true;
public static function out(message:String):void {
if (shouldTrace) {
trace(message);
}
}
}
Then throughout my application I replace all my trace() calls with:
Trace.out("trace statement");
It's not quite as smooth while developing, but I can turn off all my trace statements by setting shouldTrace when I want to compile the release SWF.

Resources