Rubymotion: NoMethodError for added method - rubymotion

I added an extra method to the String class. I want to use this method later on, but I get a no Method error.
class String
def as_file_full_path
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) [0].stringByAppendingPathComponent(self)
end
end
When I try the following in the REPL it works:
(main)> "image.jpg".as_full_path
=> "/Users/user/Library/Application Support/iPhone Simulator/6.1/Applications/30D186A9-B1C7-4377-AE91-0D14BD3B4A6D/Documents/image.jpg"
But when I call a method on a my model class, it does not work anymore:
(main)> w = Word.first
=> #<Word:0x94d7df0>
(main)> w.filename
=> "2C86A58A-A92A-4A0F-B26C-0F5F583E142C.caf"
(main)> w.filename.class
=> String
(main)> w.filename.as_full_path
2013-02-28 09:17:55.935 project[74283:c07] undefined method `as_full_path' for "2C86A58A-A92A-4A0F-B26C-0F5F583E142C.caf":String (NoMethodError)
=> NoMethodError: undefined method `as_full_path' for "2C86A58A-A92A-4A0F-B26C-0F5F583E142C.caf":String
The model is implemented using NanoStore::Model.
Edit:
When I clone the String returned by the model, the added method is present.
w.filename.dup.as_full_path
=> "/Users/user/Library/Application Support/iPhone Simulator/6.1/Applications/30D186A9-B1C7-4377-AE91-0D14BD3B4A6D/Documents/2C86A58A-A92A-4A0F-B26C-0F5F583E142C.caf"

Problem solved! For some reason extending the String class does not always work. I think the NanoStore for some reason does not return "real" ruby strings.
Solved it by replacing "String" with "NSString" so:
class NSString
def as_file_full_path
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) [0].stringByAppendingPathComponent(self)
end
end

Related

How can I test a Yii2 model in a library project?

I'm trying to implement an adapter that is using a Yii model object extending yii\db\ActiveRecord. The object is passed as constructor arg to the adapter class.
My issue is now that I still couldn't figure out how to get this to work properly. I've even tried mocking it but got stuck because Yii is using lots of static methods to get it's objects. Sure, I could now try to mock them... But there must be a better way?
public function testSuccessFullFind(): void
{
$connection = (new Connection([
'dsn' => 'sqlite:test'
]))
->open();
$queryBuilder = new \yii\db\sqlite\QueryBuilder($connection);
$app = $this->createMock(Application::class);
\Yii::$app = $app;
$app->expects($this->any())
->method('getDb')
->willReturn($this->returnValue($connection));
$userModel = new UserModel();
$resovler = new Yii2Resolver($userModel);
$result = $resolver->find(['username' => 'test', 'password' => 'test']);
// TBD asserts for the result
}
The UserModel is used to find a user record internally.
This results in:
1) Authentication\Test\Identifier\Resolver\Yii2ResolverTest::testSuccessFullFind
Error: Call to a member function getDb() on null
vendor\yiisoft\yii2-dev\framework\db\ActiveRecord.php:135
vendor\yiisoft\yii2-dev\framework\db\ActiveQuery.php:312
vendor\yiisoft\yii2-dev\framework\db\Query.php:237
vendor\yiisoft\yii2-dev\framework\db\ActiveQuery.php:133
tests\TestCase\Identifier\Resolver\Yii2ResolverTest.php:31
The code above is obviously the WIP of a test case.
So how can I configure a test connection and get my ActiveRecord object to use it?
You can pass connection as argument of all() method:
$results = UserModel::find()->where(['id' => 1])->all($connection);

MOQ - Returning value that was return by method

I have a method on an interface:
string GetUserDetails(string whatever);
I want to mock this with MOQ, so that it returns whatever the method returns i.e user details - something like:
_mock.Setup( theObject => theObject.GetUserDetails( It.IsAny<string>( ) ) )
.Returns( [object return by GetUserDetails method] ) ;
Any ideas?
For situation described in question, you need to use partial mocking. In Moq there are two different ways to achieve it:
Specifying CallBase on construction: var mock = new Mock<MyClass> { CallBase = true }; . In this case by default call on this object methods will execute real method implementation if any.
Specifying CallBase for some specific method: mock.Setup(m => m.MyMethod()).CallBase();
See also When mocking a class with Moq, how can I CallBase for just specific methods?

Doctrine don't fine findBy PhpUnit

I'm novice about phpunit.
I use this snippet to mock my EntityManager
$emMock = $this->getMock('\Doctrine\ORM\EntityManager',
array('getRepository', 'getClassMetadata', 'persist', 'flush'), array(), '', false);
$emMock->expects($this->any())
->method('getRepository')
->will($this->returnValue(new \it\foo\Entity\File()));
$emMock->expects($this->any())
->method('persist')
->will($this->returnValue(null));
$emMock->expects($this->any())
->method('getClassMetadata')
->will($this->returnValue((object) array('name' => 'aClass')));
$emMock->expects($this->any())
->method('flush')
->will($this->returnValue(null));
When I run my test I have this error
Error: Call to undefined method it\foo\Entity\File::findBy()
How can I mock this method?
If you look at your code, you will see, that at least one line of it calls getRepository() and uses the result to apply function findBy() on it. This is a very standard behavior of a Doctrine2 program.
You are mocking only the EntityManager - you have the mock in the variable $emMock. One of the (mocked) functions, getRepository() returns an object of class \it\foo\Entity\File, which you create in line 5.
I suppose that class \it\foo\Entity\File doesn't implement the same interface as a Doctrine2 repository, at least it obviously doesn't implement findBy(), so the error message occurs.
To solve this problem, you need to replace the return value of the mock function for getRepository with either e real Repository (which is normally not what you want in a unit test) or another mock:
$repoMock = $this->getMock('Doctrine\ORM\EntityRepository', [], [], '', false);
$emMock->expects($this->any())
->method('getRepository')
->will($this->returnValue($repoMock);
Most likely you have to mock some of the functions in the Repository as well, for example findBy() which may return the list of entries you want your test to work with.

when mocked method with ref parameter is used, assert MustHaveHappened fails

Im using FakeItEasy to mock methods for unit tests. One of method (using REF parameter - maybe this is important) saves data in database, so it's mocked as 'Does Nothing'
A.CallTo(() => mockedUserRepository.Save(ref mwbeUserData)).DoesNothing();
. But in this situation last assert fails
A.CallTo(() => mockedUserRepository.Save(ref mwbeUserData)).MustHaveHappened(Repeated.Exactly.Once);
with error:
Assertion failed for the following call:
MobileWallet.Common.DAL.IMwbeUserRepository.Save(<NULL>)
Expected to find it exactly once but found it #0 times among the calls:
1: MobileWallet.Common.DAL.IMwbeUserRepository.Get(userName: \"AAA\")
2: MobileWallet.Common.DAL.IMwbeUserRepository.Save(user: MobileWallet.Common.Repository.MwbeUserData)
Full code of test
[TestMethod]
public void AddUser_MwbeUserObjectReturned()
{
//Arrange
MwbeUserRegistrationIn userRegistrationIn = new MwbeUserRegistrationIn()
{
BirthDate = DateTime.Today,
Email = "www#wp.pl",
FirstName = "Adam",
SecondName = "Ada2",
UserName = "AAA"
};
//mock mockedNotificationService and related:
INotificationService mockedNotificationService = A.Fake<INotificationService>();
//TODO: create notofication service
//mock IMwbeUserRepository and related
IMwbeUserRepository mockedUserRepository = A.Fake<IMwbeUserRepository>();
MwbeReturnData<MwbeUserData> mwbeReturnData = new MwbeReturnData<MwbeUserData>(MwbeResponseCodes.NotFound);
MwbeUserData mwbeUserData = mwbeReturnData.Data;
A.CallTo(() => mockedUserRepository.Get(userRegistrationIn.UserName)).Returns(mwbeReturnData);
A.CallTo(() => mockedUserRepository.Save(ref mwbeUserData)).DoesNothing();
MwbeUserService userService = new MwbeUserService(mockedUserRepository, mockedNotificationService);
//Act
MwbeUser user = userService.AddUser(userRegistrationIn);
//Assert
Assert.IsNotNull(user);
Assert.AreEqual(userRegistrationIn.Email, user.Email);
Assert.AreEqual(userRegistrationIn.UserName, user.UserName);
Assert.AreEqual(userRegistrationIn.FirstName,user.FirstName);
Assert.AreEqual(userRegistrationIn.SecondName, user.SecondName);
Assert.AreEqual(userRegistrationIn.BirthDate, user.BirthDate);
A.CallTo(() => mockedUserRepository.Get(userRegistrationIn.UserName)).MustHaveHappened(Repeated.Exactly.Once);
A.CallTo(() => mockedUserRepository.Save(ref mwbeUserData)).MustHaveHappened(Repeated.Exactly.Once);
}
UPDATE 1:
Please notice that for both calls to this method Save, value of mwbeUserData is the same
MwbeUserData mwbeUserData = mwbeReturnData.Data;
If this is null (but it's not).
Maybe the is problem with syntax for REF parameter? I read that there should be used method called AssignsOutAndRefParameters, but I dont know exactly how to use it.
For now I will use MATCHES parameter to make it more generic.
I believes that it's occurred because you assert against mwbeUserData instance
#Old Fox has the right of it.
You're asking FakeItEasy if mockedUserRepository.Save(ref mwbeUserData) was called with null input (mwbeUserData must be null at the time you make the check). It saw nothing like that, since the MwbeUserData that was passed to mockedUserRepository.Save inside AddUser appears to have been not null.
If you think the test should've passed, perhaps relaxing your constraint will help, as in FakeItEasy: mocked method is not returning expected result.
Also, note that the refness of the parameter has no effect on this behaviour. the same constraint matching would occur for a "plain" parameter. Only out parameters are exempted by default. See Argument Constraints in the FakeItEasy documentation for more information about this, and more on how to use custom argument matchers.

scope not working on Mongoid (undefined method `to_criteria')

I invoke ReleaseSchedule.next_release in other controller
and got the following error
NoMethodError (undefined method `to_criteria' for #<ReleaseSchedule:0x007f9cfafbfe70>):
app/controllers/weekly_query_controller.rb:15:in `next_release'
releae_schedule.rb
class ReleaseSchedule
scope :next_release, ->(){ ReleaseSchedule.where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at).first }
end
That's not really a scope at all, that's just a class method wrapped up to look like a scope. There are two problems:
You're saying ReleaseSchedule.where(...) so you can't chain the "scope" (i.e. ReleaseSchedule.where(...).next_release won't do what it is supposed to do).
Your "scope" ends in first so it won't return a query, it just returns a single instance.
2 is probably where your NoMethodError comes from.
If you really want it to be a scope for some reason then you'd say:
# No `first` or explicit class reference in here.
scope :next_release, -> { where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at) }
and use it as:
# The `first` goes here instead.
r = ReleaseSchedule.next_release.first
But really, you just want a class method:
def self.next_release
where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at).first
end
The scope macro is, after all, just a fancy way to build class methods. The only reason we have scope is to express an intent (i.e. to build queries piece by piece) and what you're doing doesn't match that intent.