public function __construct(RequestSchemaInterface $requestSchema)
{
$this->schema = $requestSchema->getSchema();
}
When I run phpspec for Builder then $this->schema is always null.
In normal call it sets schema.
I got let implemented
function let(RequestSchema $requestSchema)
{
$this->beConstructedWith($requestSchema);
}
How can I test methods of that class if they use $this->schema ?
Your let() method uses a stub to construct the object under test. While this is recommended, it is not required. You can create a real object of type RequestSchema and use it to construct the tested class:
function let()
{
$requestSchema = new RequestSchema();
$this->beConstructedWith($requestSchema);
}
Update:
Regarding the title of your question "How to make phpspec evaluate my constructor": the constructor is executed but, because you use a stub for $requestSchema, the call $requestSchema->getSchema() inside the constructor returns NULL.
You can prepare the stub to return something else when its method getSchema() is called.
Try this:
function let(RequestSchema $requestSchema)
{
// Prepare the stub
$requestSchema->getSchema()->willReturn('something');
// Construct the object under test using the prepare stub
$this->beConstructedWith($requestSchema);
// Verify the constructor initialized the object properties
$this->schema->shouldBe('something');
}
Related
I'm trying to write a Jasmine test for a function of class which instantiates and observes an object from another class. Since I want to keep this test contained to the first class and to simulate different scenarios of the second I want to mock the second. Some pseudo code might help
export class Foo {
startProcessing() {
const bar = new Bar();
const sub = bar.tickTock.subscribe(
state => {
// something went right
},
error => {
// something went wrong
}
);
}
}
I've tried declaring the mock class in my test file, and providing it through TestBed.configureTestingModule's providers attribute, but it always uses the original Bar.
How can I write a test that provides a mock class in place of Bar that I can control?
One way to get around this issue is to pass in object of type Bar through function parameter (dependency injection). That way you can have control over Bar object.
Can someone please help .
The scenario is that i want to call a new method from inside of other method calls without affecting the processing happening in methods a(),b(),c()
Also, any exception in method newClass.d(id) should not affect processing in a(),b(), c()
ideally would like to call newClass.d(id) after method a() has completed its processing
method a()
{
//calls
method b()
}
#transnational
method b()
{
//calls method c
method c()
}
method c()
{
//this stores some value into database and gets an id
//I need this id and want to call another method d(pass ID)
// i want to call it in a way that if there is any exception in method d(pass ID), its should not affect a(),b(),c()
}
class newClass
{
method d(id)
{
//does something
}
}
Is there any better way of doing this in Spring.
Thanks
Regards
If NewClass is a service/component, and you call it within methodC like
newClassInstance.methodD()
Then i would suggest adding an annotation on methodD
#Transactional(propagation=REQUIRES_NEW)
Doing so, spring will start a new transaction for methodD execution, and if this one fail, it will rollback only changes made in methodD
But, if an exception is thrown from methodD without being catched, it will rollback also previous transaction
I am writing unittest for void method actually that method load the collection in
ViewData["CityList"] method is
public void PopulateCityCombo() {
IEnumerable<Cities> c= service.GetCities();
ViewData["CityList"] = c.Select(e => new Cities{ ID = e.ID, Name = e.Name});
}
now i do not know how to unit test using Moq since controller method is void and not returning data, can any one tell i will achive that.
On a side note, I would shy away from using ViewData within controller methods as per your example. The ViewData dictionary approach is fast and fairly easy to implement, however it can lead to typo's and errors that are not caught at compile time. An alternative would be to use the ViewModel pattern which allows you to use strongly-typed classes for the specific view you need to expose values or content within. Ultimately giving you type safe and compile time checking along with intellisense.
Switching to the ViewModel pattern would allow you to call the PopulateCityCombo() method from your controller to populate a ViewModel that in turn would passed to the corresponding view.
From there you would need to inject a mock service layer into your controllers constructor from your unit test.
// arrange
var mock = new Mock<servicelayer>();
mock.Setup(x=>x.GetCities()).Returns(expectedData);
var controller = new YourController(mock.Object);
// act
var result = controller.ControllerMethod() as ViewResult;
var resultData = (YourViewModel)result.ViewData.Model;
// assert
// Your assertions
I'm using Ninject 1.0 and would like to be able to inject lazy initialisation delegates into constructors. So, given the generic delegate definition:
public delegate T LazyGet<T>();
I'd simply like to bind this to IKernel.Get() so that I can pass a lazy getter into constructors, e.g.
public class Foo
{
readonly LazyGet<Bar> getBar;
public Foo( LazyGet<Bar> getBar )
{
this.getBar = getBar;
}
}
However, I can't simply call Bind<LazyGet<T>>() because it's an open generic type. I need this to be an open generic so that I don't have to Bind all the different lazy gets to explicit types. In the above example, it should be possible to create a generic delegate dynamically that invokes IKernel.Get<T>().
How can this be achieved with Ninject 1.0?
Don't exactly understand the question, but could you use reflection? Something like:
// the type of T you want to use
Type bindType;
// the kernel you want to use
IKernel k;
// note - not compile tested
MethodInfo openGet = typeof(IKernel).GetMethod("Get`1");
MethodInfo constGet = openGet.MakeGenericMethod(bindType);
Type delegateType = typeof(LazyGet<>).MakeGenericType(bindType);
Delegate lazyGet = Delegate.CreateDelegate(delegateType, k, constGet);
Would using lazyGet allow you to do what you want? Note that you may have to call the Foo class by reflection as well, if bindType isn't known in the compile context.
I am fairly certain that the only way to do this (without some dirty reflection code) is to bind your delegate with type params. This will mean it needs to be done for each individual type you use. You could possibly use a BindingGenerator to do this in bulk, but it could get a bit ugly.
If there is a better solution (a clean one) I would love to hear it as I run into this problem from time to time.
From another similar question I answered:
public class Module : NinjectModule
{
public override void Load()
{
Bind(typeof(Lazy<>)).ToMethod(ctx =>
GetType()
.GetMethod("GetLazyProvider", BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(ctx.GenericArguments[0])
.Invoke(this, new object[] { ctx.Kernel }));
}
protected Lazy<T> GetLazyProvider<T>(IKernel kernel)
{
return new Lazy<T>(() => kernel.Get<T>());
}
}
I have a LINQ object with an additional method added to it. The class has no disposable properties or methods, but FxCop is raising the error "Types that own disposable fields should be disposable" and referencing that class.
I've reduced the code this far and still receive the error:
partial class WikiPage
{
public PagePermissionSet GetUserPermissions(Guid? userId) {
using (WikiTomeDataContext context = new WikiTomeDataContext()) {
var permissions =
from wiki in context.Wikis
from pageTag in context.VirtualWikiPageTags
select new {};
return null;
}
}
}
However, if I remove EITHER of the from clauses, FxCop stops giving the error:
partial class WikiPage
{
public PagePermissionSet GetUserPermissions(Guid? userId) {
using (WikiTomeDataContext context = new WikiTomeDataContext()) {
var permissions =
from pageTag in context.VirtualWikiPageTags
select new {};
return null;
}
}
}
Or
partial class WikiPage
{
public PagePermissionSet GetUserPermissions(Guid? userId) {
using (WikiTomeDataContext context = new WikiTomeDataContext()) {
var permissions =
from wiki in context.Wikis
select new {};
return null;
}
}
}
PagePermissionSet is not disposable.
Is this a false positive? Or is the LINQ code somehow generating a disposable field on the class? If it isn't a false positive, FxCop is recommending that I implement the IDisposable interface, but what would I do in the Dispose method?
EDIT:
The full FxCop error is:
"Implement IDisposable on 'WikiPage' because it
creates members of the following IDisposable types:
'WikiTomeDataContext'. If 'WikiPage' has previously
shipped, adding new members that implement IDisposable
to this type is considered a breaking change to existing
consumers."
Edit 2:
This is the disassembled code that raises the error:
public PagePermissionSet GetUserPermissions(Guid? userId)
{
using (WikiTomeDataContext context = new WikiTomeDataContext())
{
ParameterExpression CS$0$0001;
ParameterExpression CS$0$0003;
var permissions = context.Wikis.SelectMany(Expression.Lambda<Func<Wiki, IEnumerable<VirtualWikiPageTag>>>(Expression.Property(Expression.Constant(context), (MethodInfo) methodof(WikiTomeDataContext.get_VirtualWikiPageTags)), new ParameterExpression[] { CS$0$0001 = Expression.Parameter(typeof(Wiki), "wiki") }), Expression.Lambda(Expression.New((ConstructorInfo) methodof(<>f__AnonymousType8..ctor), new Expression[0], new MethodInfo[0]), new ParameterExpression[] { CS$0$0001 = Expression.Parameter(typeof(Wiki), "wiki"), CS$0$0003 = Expression.Parameter(typeof(VirtualWikiPageTag), "pageTag") }));
return null;
}
}
Edit 3:
There does appear to be a closure class containing a reference to the DataContext. Here is its disassembled code:
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
// Fields
public WikiTomeDataContext context;
// Methods
public <>c__DisplayClass1();
}
My guess is that the two From clauses generate a call to SelectMany with a closure on your data context. The instance of the closure has a field to the datacontext which is causes the FxCop warning. This is nothing to worry about.
There's only one instance of your datacontext, which you clean up via the using block. Because the closure doesn't have a finalizer there's no performance or saftey implication here in the FxCop warning.
I noticed that this is a partial class. Have you checked the other implementation file for the class and see if it has an IDisposable member that is not being disposed?
I don't think the generated closure is at fault here. Closures are generated with certain attributes that should cause FxCop to ignore warnings like this.
EDIT
Further investigation by the OP showed this to be an issue with an IDisposable field being lifted into a closure.
Unfortunately there isn't a whole lot you can do about this. There is no way to make the closure implement IDisposable. Event if you could there is no way to call IDisposable on the closure instance.
The best way to approach this problem is to rewrite your code in such a way that a disposable value does not get captured in the closure. Disposable fields should always be disposed when they are finished and capturing it in a closure prevents you from doing this.
If you're returning a LINQ query from your method, consumers will iterate over the results using foreach.
When a consumer finishes a foreach loop, it internally calls dispose on the IEnumerable source (in this case, your LINQ query). This will dispose the WikiTomeDataContext.
However, if a consumer made a call to method returning a LINQ query but never iterated over the results, it would appear that enumerable would never be disposed (that is, until the garbage collector cleaned up the object). This would lead to your WikiTomeDataContext not being disposed until garbage collection.
One way you might be able to get around this problem is by calling .ToArray on the result of your LINQ query, call dispose on your context, then return the array.
Your code that gives the error uses WikiDataContext.
Your two examples that do not give an error use WikiTomeDataContext.
Maybe there is some difference between these two that is causing the error.