I'm testing an MVC controller which relies on a value returned from a read-only property on the base class.
The getter for this property throws an exception when it is called as it is relies on a HttpContext (and other nasty stuff) which I would rather avoid mocking.
This is what I've tried so far:
controller = Substitute.ForPartsOf<MyController>(
Substitute.For<SomeDependency>(),
);
controller.UserInfo.Returns(new UserInfo());
Yet this throws an exception as soon as UserInfo is accessed.
Property on base class is:
public UserInfo UserInfo
{
get
{
// HttpContext dependent stuff
}
}
I've tried setting the base class property to virtual but then I get a Castle proxy exception.
I think you may be having another problem. NSubstitute is capable of handling substitution of virtual properties. Here is a small program that illustrates
public class SubstitutedClass
{
public virtual int SubstitutedProperty { get { throw new InvalidOperationException(); } }
}
internal class Program
{
private static void Main(string[] args)
{
var test2 = Substitute.For<SubstitutedClass>();
test2.SubstitutedProperty.Returns(10);
Console.WriteLine(test2.SubstitutedProperty);
}
}
EDIT: Regarding your use of ForPartsOf I don't think it is possible to override a property this way, since there is no way of informing NSubstitute that we don't want it to call the base code. That's why the documentation mentions that partial sub are not recommended
You could change the base class in order to return the value of a virtual function; this virtual function would then be substituted. No signature change for the callers. Although this is a hack you would get what you need
public class SubstitutedClass
{
public virtual int SubstitutedProperty { get { return InnerValue(); } }
public virtual int InnerValue() { throw new InvalidOperationException(); }
}
var test2 = Substitute.ForPartsOf<SubstitutedClass>();
test2.When(t => t.InnerValue()).DoNotCallBase();
test2.InnerValue().Returns(10);
Related
I am building some integration tests for my database stored procedures.
I have setup an xUnit project and implemented Fixture pattern. To show you:
public class MyTableTest : IClassFixture<DatabaseFixture>
{
public MyTableTest()
{
//DO SOMETHING
}
[Fact]
public void Test()
{
//DO SOMETHING
}
}
And:
public class DatabaseFixture : IDisposable
{
public void Dispose()
{
// ... clean up test data from the database ...
}
}
This DatabaseFixture is something that will be shared among all of my test classes. Why? Because I want some common logic happening at the end of every test, such as cleanup.
Point is that I need to know which table to clean, which in my example would be MyTable. Such information I would retrieve by using reflection when the Dispose method will run against the instance of MyTableTest being disposed . How can I achieve this? Is it even possible (and correct) trying to achieve this? Thanks in advance.
You can have a TableName property in the DatabaseFixture class. Then receive an instance of the class in constructor of your test classes and set that TableName property. Later you can use it in dispose to do some cleanup.
public class MyTableTest : IClassFixture<DatabaseFixture>
{
DatabaseFixture databaseFixture;
public MyTableTest(DatabaseFixture databaseFixture)
{
this.databaseFixture = databaseFixture;
databaseFixture.TableName = "MyTable";
}
[Fact]
public void Test()
{
}
}
public class DatabaseFixture : IDisposable
{
//...
public string TableName { get; set; }
//...
public void Dispose()
{
// Cleanup based on TableName
}
}
To learn more about sharing context in xUnit, take a look at:
Shared Context between Tests
Comparing xUnit.net to other frameworks
You can use custom attributes to attach any arbitrary data to your derived Fixture class.
For example
you can create a TableNameAttribute like this:
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class TableNameAttribute : Attribute
{
public string Name { get; }
public TableNameAttribute(string name)
{
this.Name = name;
}
}
you can apply this attribute to your derived fixture class:
[TableName("MyTable")]
public class MyTableFixture : DatabaseFixture { }
you can use that fixture class inside your test
public class MyTableTest : IClassFixture<MyTableFixture>
{
[Fact]
public void Test()
{
//DO SOMETHING
}
}
Finally this is how you can retrieve the Name from the Dispose method:
public abstract class DatabaseFixture : IDisposable
{
...
public void Dispose()
{
var attribute = this.GetType().GetCustomAttribute(typeof(TableNameAttribute));
if (attribute is TableNameAttribute tableNameAttr)
Console.WriteLine(tableNameAttr.Name);
}
}
Is it even possible (and correct) trying to achieve this?
No. Reflection cannot tell type T in what context T is used; reflection only sees T's declaration.
More specific to your situation, reflection cannot tell type DatabaseFixture that it is being used as a type parameter of generic interface IClassFixture in the declaration of MyTableTest. In other words, for this set of declarations,
class A { }
class B <T> { }
class C : B<A> { }
A cannot reflectively determine that it is used in C's declaration, but C can know about its usage of A:
typeof(C)
.BaseType // B
.GetGenericArguments()[0] // A
How can I achieve this?
Depending on how you are using DatabaseFixture, you could get the calling test class using the StackTrace (if you are really bent on using reflection). Here is a simple example:
public class DisposableObject : System.IDisposable
{
public void Dispose()
{
var stack = new System.Diagnostics.StackTrace();
// This will log the name of the class that instantiated and disposed this.
System.Console.WriteLine(stack.GetFrame(1).GetMethod().DeclaringType.Name);
return;
}
}
If your DatabaseFixture is not called directly from your test class, you will either have to know the offset to pass to GetFrame(int), or you will need to search each frame until you find the first DeclaringType that matches your requirements (e.g., BaseType is IClassFixture with Generic Argument DatabaseFixture), something like this:
System.Type testClassType = new StackTrace()
.GetFrames()
.Where(f =>
{
System.Type baseType = f.GetMethod().DeclaringType.BaseType;
return typeof(IClassFixture<DatabaseFixture>).IsAssignableFrom(baseType);
})
.FirstOrDefault() // First matching result (assuming you found any)
?.GetMethod() // Get the reflected Method
.DeclaringType; // Get the type (e.g. class) that declares this method.
string tableName = testClassType.Name.Replace("Test", "");
Otherwise, you will need to set the table name manually, as suggested by Reza and Peter.
I am mocking an abstract class with NSubstitute and expect its protected virtual method to be called.
public abstract class A
{
protected virtual bool ProtectedMethod()
{
return true;
}
public bool PublicMethod()
{
return ProtectedMethod();
}
}
public class ATest
{
[Fact]
public void Test()
{
var anA = Substitute.For<A>();
var result = anA.PublicMethod();
Assert.True(result);
}
}
This test fails when executed. In fact, it fails even if the class is not abstract. If this is normal behavior, what should I do to ensure the ProtectedMethod is called?
PS. If the method is not virtual, it works as expected.
As pointed out in the comments, be careful substituting for classes. I recommend installing the NSubstitute.Analyzers to pick up issues with class substitutes at compile time.
The reason this test is failing is because you are substituting for A, so NSubstitute replaces all virtual implementations with substitute ones (which generally return default unless otherwise stubbed out, in this case false).
You can use a partial substitute which will maintain the existing implementation by default (i.e. ProtectedMethod will keep returning true as per the base implementation):
[Fact]
public void TestUsingPartialSub() {
var anA = Substitute.ForPartsOf<A>();
var result = anA.PublicMethod();
Assert.True(result);
}
"... what should I do to ensure the ProtectedMethod is called?"
NSubstitute can not assert on protected methods (it works via the publicly accessible API). If possible, you can refactor the code to use a strategy pattern to inject the protected behaviour. This will make the code more flexible (including the flexibility to inject different behaviour for testing), at the cost of a slightly more complex design.
public interface IProtectedMethod {
bool ProtectedMethod();
}
public class AA {
private readonly IProtectedMethod x;
public AA(IProtectedMethod x) {
this.x = x;
}
public bool PublicMethod() {
return x.ProtectedMethod();
}
}
public class AATest {
[Fact]
public void TestUsingStrategySub() {
var x = Substitute.For<IProtectedMethod>();
var anA = new AA(x);
anA.PublicMethod();
x.Received().ProtectedMethod();
}
}
(Please excuse the naming in this example, I've tried to keep it similar to the original to make it clearer where the various bits of logic have moved.)
While I'm testing the Castle DynamicProxy I found an weird behavior
I didn't found good documentation, so the closer information I found was theses 2 ask
Castle Dynamic Proxy not intercepting method calls when invoked from within the class
and
Why won't DynamicProxy's interceptor get called for *each* virtual method call?
and with it, I suppose that, when you use the CreateClassProxyWithTarget everything goes into the Class and back to the proxy, so if the Prop/function is not virtual, it only return the Class value.
I guess, with code sample, my question get clear.
Let's suppose I have this code
Main
private static void Main(string[] args)
{
var theObj = new SomeClass
{
NonVirtualString = "Non virtual value",
VirtualString = "Virtual value"
};
var theProxy = Interceptor.AddProxy(theObj);
Console.WriteLine($"OBJ NonVirtualString: {theObj.NonVirtualString } || VisrtualString {theObj.VirtualString }");
Console.WriteLine($"Proxy NonVirtualString: {theProxy.NonVirtualString } || VisrtualString {theProxy.VirtualString }");
}
public class SomeClass
{
public string NonVirtualString { get; set; }
public virtual string VirtualString { get; set; }
}
Interceptor
public static class Interceptor
{
private static readonly ProxyGenerator _generator = new ProxyGenerator();
public static TEntity AddProxy<TEntity>(TEntity entity) where TEntity: class, new()
{
var proxy = _generator.CreateClassProxyWithTarget(entity, new LogInterceptor());
return proxy;
}
}
Logger
[Serializable]
public class LogInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
Console.WriteLine("Intercepting: {0} with value: {1}", invocation.Method.Name, invocation.ReturnValue);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Exception in method {0}{1}{2}", invocation.Method.Name,
Environment.NewLine, ex.Message));
throw;
}
}
}
the result is
OBJ NonVirtualString: Non virtual value || VisrtualString Virtual value
Intercepting: get_VirtualString with value: Virtual value
Proxy NonVirtualString: NULL || VisrtualString Virtual value
And the expected result would be
OBJ NonVirtualString: Non virtual value || VisrtualString Virtual value
Intercepting: get_VirtualString with value: Virtual value
Proxy NonVirtualString: Non virtual value || VisrtualString Virtual value
So, if the result is right, how I can do, with Castle or other Lib what I'm trying(Only overhide the virtual and keep the non virtual accessible ?
You probably can't. Not with the composition-based CreateClassProxyWithTarget, anyway. When you are calling a non-virtual method on such a proxy object, you're completely bypassing DynamicProxy; it cannot intercept that invocation and therefore won't forward it to the target object. Thus you get back the value of the proxy object's own uninitialized NonVirtualString property.
You could get this to work with inheritance-based proxying, i.e. with CreateClassProxy. Using that approach, you'll only have one object (the proxy) instead of two, so you'd set the property values directly on the proxy object instead of on a separate target. Then, even though DynamicProxy still won't be able to intercept the call to NonVirtualString's getter, the call will just use the original class' getter.
Because the property is not virtual the proxy class cannot override it. When you call Interceptor.AddProxy() it creates a new object of type that inherits from SomeClass. This object will have its own values of VirtualString and NonVirtualString. VirtualString Will be overridden by the library to use Interceptor, but NonVirtualString will not be overriden and will remain NULL, as it's the default for string.
You might try to use Interface interception instead. Otherwise, you won't be able to intercept a non virtual methods/properties.
Ok, edited the code for clarification:
Question: How can I access the attribute [MyAttr("...")] in TestClassOne/Two from BaseClass.TheAttribute...?
All classes except TestClassOne/Two will be compiled in to my "core" and delivered as a dev-platform to a customer.
The TestClassOne/Two is developed by the customer, so there can be no knowledge of the TestClassOne/Two in the "core".
Code below is compiled into "core" and delivered to customer as dll.
[TestMethod()]
public void AttrTest()
{
var one = new TestClassOne();
var attrOne = one.MyTestProperty.TheAttribute;
var two = new TestClassTwo();
var attrTwo = two.MyTestProperty.TheAttribute;
}
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
}
public class BaseClass
{
public string TheAttribute
{
get {
// Here I would like to get the "[MyAttr("...")]" from the classes in the bottom
return null;
}
}
}
public class SubClass : BaseClass
{
}
Code below is developed by customer (using my dll's)
public class TestClassOne
{
[MyAttr("Attribute one")]
public SubClass MyTestProperty = new SubClass();
}
public class TestClassTwo
{
[MyAttr("Attribute two")]
public SubClass MyTestProperty = new SubClass();
}
You can get directly from type Test:
var result = typeof (Test)
.GetField("MyTest", BindingFlags.Public | BindingFlags.Instance)
.GetCustomAttribute<MyAttr>();
Edit 3:
You can walk the call stack, looking for a relevant attribute in a relevant member in a relevant class. Try this:
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
public string getAttr()
{
return _test;
}
}
public class BaseClass
{
private string theString;
public BaseClass()
{
StackTrace callStack = new StackTrace();
for ( int i = 0; i < callStack.FrameCount; i++ )
{
Type t = callStack.GetFrame(i).GetMethod().DeclaringType;
foreach ( MemberInfo m in t.GetMembers().Where(x => typeof(BaseClass).IsAssignableFrom(x.Type)) )
{
foreach ( var z in m.GetCustomAttributes(typeof(MyAttr)) )
{
MyAttr theAttr = z as MyAttr;
if ( z!= null )
{
theString = z.getAttr();
return;
}
}
}
}
}
public string Test
{
get {
return theString;
}
}
}
This requires that your customer always initializes the SubClass member inside the class that declares it. If they start deriving TestClassOne or have it and TestClassTwo derive from a common class that initializes the member, this code will break.
With clever use of reflection, you can expand the above code to cover more use cases, but that's beyond the scope of this question.
Edit 2:
No. I'm sorry, but what you're trying to do isn't possible. There's no "normal" way for an instance of SubClass to know if it's being declared in a member field of some other object, or in an element in an array or in a temporary variable in the stack, or whatever. As such, there's no way for that instance to access the attributes of the member field that's declaring it.
(I suppose you might want to try to access the garbage collector to find out where in memory the this object lives, but that's probably way beyond the scope of this problem, and in any case, not something I know how to do.)
I suspect your problem lies elsewhere entirely. Maybe you need to require your customer to make TestClassOne and TestClassTwo derive from a common abstract class. Maybe they need to derive from BaseClass themselves. Maybe you need to add parameters to the constructor. Maybe you need to provide a different interface altogether. We can't know unless you provide more information on your specific business requirements.
Edit:
To access the attributes declared on the MyTest member, try something along these lines:
public class BaseClass
{
public string Test
{
get {
var attr = typeof(Test).GetMembers().Where(x => x.Type == this.GetType()).First().GetCustomAttributes(true);
return null;
}
}
}
This will search class Test for a member with the same type as this and look for attributes on that member.
(I don't have my Visual Studio here, to check the exact Where syntax, but it should be pretty close to that...)
Original Answer:
Your attribute is declared on the MyTest member of class Test. But, you're doing GetCustomAttributes on class SubClass itself.
Try this:
[MyAttr("apa")]
public class SubClass : BaseClass
{
}
public class Test
{
public SubClass MyTest = new SubClass();
}
Should get you what you want.
I have a structure which looks basicly like this:
abstract class A
{
protected string Identificator { get; set; }
private void DoSomething()
{
// ...
DoSomethingSpecific();
}
protected abstract void DoSomethingSpecific();
}
Because of the complexity I need do unit tests the DoSomething method to be sure it works allways in the same way. Thats why I created following stub.
public class AStub : A
{
protected override void DoSomethingSpecific()
{
// nothing to do
}
}
I use the PrivateObject class to access the methods and properties of class A be instantiating class AStub. This worked for a while and for some reason crashes now whenever I try to access either the property or the method.
following code for testing:
var sut = new CommonIodAdapterImpl();
var accessor = new PrivateObject(sut);
accessor.SetProperty("Identificator", "blablub");
accessor.Invoke("DoSomething", null);
// assert...
The exception which is thrown is a MissingMethodException telling me that the propertie or method was not found. But when I debug and check the hierachy every seems to be right inclduing the spelling.
Thank you for your help.
You need to set the PrivateType argument to your base class to access the private members at that level.
var accessor = new PrivateObject(sut, new PrivateType(typeof(A)));
Shouldn't that be "public class AStub : A"?
To resolve the missing method exception just compile everything(!) once more. Either you get some compiler error telling you what's wrong or the error will vanish.
If it still doesn't work, check if you don't have multiple copies of the assemblies (including GAC!) and watch in the Deboug-Out-Window if it loads the assemblies from the correct path.
I just tried something similar, i assmued it's because the property is protected rather than private.
I created my own accessor in my test assembly
public class AAccessor : A
{
// use this instead of Identificator
public string IdentificatorAccessor
{
get { return this.Identificator; }
set { this.Identificator = value; }
}
// test this method in your unit test
public void DoSomethingAccessor()
{
this.DoSomethingSpecific()
}
// need this to satisfy the abstract class
protected override void DoSomethingSpecific()
{
// do nothing here
}
}
public class BaseClass
{
private int _fieldToSet;
...
}
public class DerivedClass : BaseClass
{
...
}
// Unit Test Code
public void Test()
{
DerivedClass d = new DerivedClass();
PrivateObject privObj = new PrivateObject(d, new PrivateType(typeof(BaseClass));
privObj.SetFieldOrProperty("fieldToSet", 8675309);
...
}