Saturday, September 22, 2007
Sorry. We moved to different location.
Sunday, April 29, 2007
Testing Non-Public members with MbUnit (Part II).
Following methods are marked as obsolete. My guess is that these methods are going to be gone completely in version 3.
| Old Method | New Method |
| GetNonPublicField | GetField |
| GetNonPublicVariable | GetField |
| GetNonPublicProperty | GetProperty |
| RunPrivateMethod | InvokeMethod |
| RunNonPublicMethod | InvokeMethod |
There're also new methods:
SetField - Sets field value.
SetProperty - Sets property value.
Thanks to Jeff who pointed out that Reflector didn’t have these methods. He also mentioned that method names between static and instance implementation are inconsistent. This also was corrected.
Let's create SampleClass:
public class SampleClass
{
public string publicString = "MbUnit Rocks!!!";
private DateTime privateDateTime = DateTime.Today;
internal DateTime InternalProperty
{
get { return privateDateTime; }
set { privateDateTime = value; }
}
private static int Add(int x, int y)
{
return x + y;
}
}
Here an example how we can create tests for SampleClass:
TestSample _sampleObject;
Reflector _reflect;
[TestFixtureSetUp]
public void Init()
{
_sampleObject = new SampleClass();
_reflect = new Reflector(_sampleObject);
}
[Test]
public void GetPublicField()
{
Assert.AreEqual("MbUnit Rocks!!!", _reflect.GetField("publicString"));
}
[Test]
public void SetNonPublicProperty()
{
string propertyName = "InternalProperty";
DateTime dt = new DateTime(2008, 1, 1);
_reflect.SetProperty(propertyName, dt);
Assert.AreEqual(dt, _reflect.GetProperty(propertyName));
}
[Test]
public void StaticPrivateMethod()
{
Assert.AreEqual(7, _reflect.InvokeMethod("Add", 1, 6));
}
I mentioned before that static and instance methods now have consistent names.
You can implement StaticPrivateMethod test like this using static implementation of InvokeMethod(..).
[Test]
public void StaticPrivateMethod()
{
Assert.AreEqual(7, Reflector.InvokeMethod(new SampleClass(), "Add", 1, 6));
}
Here's another of Jeff's suggestions:
Indicating public vs. non-public is useful for documentation purposes.
Once again, because of Jeff's suggestion we have AccessModifier enum type and using it we can specify if we want to access public, static, or non-public member. In examples above we didn't use AccessModifier. It means that Reflector will invoke method or access field or property as long as an object has implementation for it.
In the example below we are trying to test Add method that has private static modifier. However, if Add method wasn't static or was public, an assirtion would happen in our test.
[Test]
public void StaticPrivateMethod()
{
Assert.AreEqual(7, _reflect.InvokeMethod(AccessModifier.Static | AccessModifier.NonPublic, , "Add", 1, 6));
}
It's a new code that was checked in; however, it has not been built yet. These and some other new features should be available in a next MbUnit build.
Thursday, April 12, 2007
Duration in MbUnit
The test below will fail because in Duration attribute we set duration for one second but inside the test we sleep for 2 seconds.
[Test]
[Duration(1)]
public void DurationFailTest()
{
Thread.Sleep(2000);
}
Next test will succeed because we don’t sleep at all.
[Test]
[Duration(1)]
public void DurationSuccessTest()
{
Thread.Sleep(0);
}
You can use it with RowTest attribute. Row(0) will succeed and Row(2000) will obviously fail.
[RowTest, Duration(1)]
[Row(0)]
[Row(2000)]
public void DurationRowTest(int sleepTime)
{
Thread.Sleep(sleepTime);
}
Tuesday, April 10, 2007
TypeMock too powerful to use
It was then. Today I believe that TypeMock is bad for the same reason I loved it before. It’s too powerful. It doesn’t force you to write a testable code.
The reason I found Rhino.Mocks hard to use is because I haven't learn yet about Inversion of Control Containers and the Dependency Injection pattern. Today I write my own mock objects without using any framework. However, if you want to use a Mock Framework, I strongly recommend Rhino.Mocks.
If you're not familiar with this pattern I recommend to read Jeremy Palermo's article Simple dependency injection to get you started with unit testing.
Testing Non-Public members with MbUnit
Let’s create MyClass with non-public members:
public class MyClass
{
private string _field = "Private";
private string PrivateProperty
{
get { return _field; }
}
private string GetHello()
{
return "Hello";
}
private int PrivateAdd(int x, int y)
{
return x + y;
}
protected double PrivateAdd(double x, double y)
{
return x + y;
}
}
As you can see we have one private field, one private property, two private methods, and one protected. Two PrivateAdd methods were created to show that you can test overloaded methods.
First, let’s create MyClassTests class that will test MyClass. In order to use MbUnit Framework, we need to add reference to MbUnit.Framework.dll.
Also we need to add reference to MbUnit.Framework.2.0.dll. The later one has Reflector class that we’re going to use to test private and protected members.
We have a choice of using static methods of Reflector class or create an instance of Reflector. I’m personally not a big fan of static methods. Currently using static methods you can test only non-public fields and methods without arguments. If some people would like to be able to test properties and methods with arguments using static methods, just let MbUnit community know and the will be happy to add it for you.
One more thing: if a name of a member incorrect, an exception is thrown with a similar message:
Fail to find NoExisit Method in MyClass.MyClass.
Well, enough talking here's the fixture:
[TestFixture]
public class MyClassTests
{
Reflector _reflector;
[TestFixtureSetUp]
public void FixtureInit()
{
MyClass myClass = new MyClass();
_reflector = new Reflector(myClass);
}
[Test]
public void PrivateField_Test()
{
Assert.AreEqual("Private"
,_reflector.GetNonPublicField("_field"));
}
[Test]
public void Static_PrivateField_Test()
{
Assert.AreEqual("Private"
, Reflector.GetNonPublicVariable(new MyClass(), "_field"));
}
[Test]
public void PrivateProperty_Test()
{
Assert.AreEqual("Private"
, _reflector.GetNonPublicProperty("PrivateProperty"));
}
[Test]
public void PrivateMethodNoArguments_Test()
{
Assert.AreEqual("Hello"
, _reflector.RunPrivateMethod("GetHello"));
}
[Test]
public void Static_PrivateMethodNoArguments_Test()
{
Assert.AreEqual("Hello"
, Reflector.RunNonPublicMethod(new MyClass(), "GetHello"));
}
[Test]
public void PrivateMethod_Test()
{
Assert.AreEqual(5
, _reflector.RunPrivateMethod("PrivateAdd", 2, 3));
}
[Test]
public void ProtectedMethod_Test()
{
Assert.AreEqual(5.6
, _reflector.RunPrivateMethod("PrivateAdd", 3.5, 2.1));
}
[Test]
[ExpectedException(typeof(ApplicationException))]
public void NonExstingMethod_Test()
{
_reflector.RunPrivateMethod("NoExisit");
}
}
Sunday, April 8, 2007
Timer class
Here’s there Timer class:
public class Timer
{
long _start;
long _stop;
public void Start()
{
_start = GetTimeInMilliseconds();
}
public void Stop()
{
_stop = GetTimeInMilliseconds();
}
public long TimeElapsed
{
get { return _stop - _start; }
}
private long GetTimeInMilliseconds()
{
return DateTime.Now.Hour * 60 * 60 * 1000
+ DateTime.Now.Minute * 60 * 1000
+ DateTime.Now.Second * 1000
+ DateTime.Now.Millisecond;
}
}
In case you’re interested in performance difference between SqlDataReader and DataTableReader. Here’re my findings:
On single CPU machine SqlDataReader was faster and it of course was expected. However, on double CPU machine DataTableReader was slightly faster and this was a pleasant surprise for me.
Tuesday, April 3, 2007
Fixture order with MbUnit
B_Fixture
…
N_Fixture
Bad_Fixture
B_Fixture
B_Child_Fixture
[TestFixture]
public class A_Fixture
{
[Test]
public void Success()
{ }
}
public class Bad_Fixture
{
[Test]
public void Failure()
{
Assert.IsTrue(false);
}
public void Success()
{
}
}
[DependsOn(typeof(A_Fixture))]
[DependsOn(typeof(Bad_Fixture))]
public class B_Fixture
{
[Test]
public void Success()
{
}
}
[DependsOn(typeof(B_Fixture))]
public class B_Child_Fixture
{
[Test]
public void Success()
{
}
}
You can see that B_Child_Fixture depends on B_Fixture. B_Fixture at the same time depends on A_Fixture and Bad_Fixture. As you can see one of the tests in Bad_Fixture will fail. As a result B_Fixture and B_Child will not run.
