Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mock with a private field failed #8

Closed
luckymark opened this issue Sep 28, 2018 · 12 comments
Closed

mock with a private field failed #8

luckymark opened this issue Sep 28, 2018 · 12 comments

Comments

@luckymark
Copy link

when I do this:

class Foo { 
    private field: string
}
let mock: Foo = Substitute.for<Foo>()

I get :error TS2322: Type 'ObjectSubstitute<Pick<Foo, never>, Foo>' is not assignable to type 'Foo'.
Property 'field' is missing in type 'ObjectSubstitute<Pick<Foo, never>, Foo>'.

when I change "private" to "public", its ok!

@ffMathy
Copy link
Owner

ffMathy commented Sep 28, 2018

What is the use case for this?

Why do you have a class only with private fields that you want to mock?

You should only test publically exposed functionality.

@joshribakoff
Copy link

Why do you have a class only with private fields that you want to mock?

He doesn't. He distilled the example, to simplify it for us.

You should only test publically exposed functionality.

Thats what hes trying to do...

class Foo { 
	private field: string
	public bar() {}
}
let mock: Foo = Substitute.for<Foo>() // error TS2322: 

The problem is he typed the mock to Foo, use the provided generic or let TS infer & it works fine:

ObjectSubstitute<OmitProxyMethods<Example>, Example>;

User error.

@luckymark
Copy link
Author

luckymark commented Sep 29, 2018

@joshribakoff yes,I just simplify the test case!
In my use case, maybe I have a class :

class A{
   public needMock:Foo
}

the field needMock will be injected by some other code...I cant wait TS infer it!

@ffMathy
Copy link
Owner

ffMathy commented Sep 29, 2018

Ah I see! Yes, that should be resolved as soon as possible!

I'll look into it sometime next week, as I am quite busy lately.

In the meanwhile, PRs are welcome!

@ffMathy
Copy link
Owner

ffMathy commented Oct 24, 2018

I made a branch now called progress where I am refactoring the whole thing into being based on a strategy pattern.

You can follow up on the progress there. However, I don't have much time lately. Feel free to fork that branch and continue.

@ffMathy
Copy link
Owner

ffMathy commented Feb 2, 2019

We can't fix this without breaking other things, until this feature is implemented:

microsoft/TypeScript#22677

@ffMathy ffMathy closed this as completed Feb 2, 2019
@ilancohen
Copy link

@ffMathy - I really like this library, but without this fixed, using this library for Angular with its dependency injection is basically a non-starter. For instance, I have a class that depends on a service that I want to mock:

@Injectable({
  providedIn: "root"
})
export class LocaleService {
  constructor(private translate: TranslateService) {
  }

  getLocale() {
    return {};
  }

  getSupportedLocales(): any[] {
    return {};
  }
}

Mocking LocaleService (for usage in initializing your class) will throw a TS error, since translate is not defined.

Any suggestions? I'm happy to help fix this with a pull request, if you have a suggestion.

@ffMathy
Copy link
Owner

ffMathy commented Feb 17, 2019

Can you provide a minimal example to reproduce it? Perhaps a PR that adds a unit test or similar? Or a separate project that demonstrates the problem?

@ffMathy ffMathy reopened this Feb 17, 2019
@ilancohen
Copy link

I haven't tested it, but I think the code below provides a minimal example.
In this scenario, we're trying to mock ClassB to test ClassC:

class ClassA {
	constructor(){}

	methodA(): string {
		return 'abc'
	}
}

class ClassB {
	constructor(
		private classA: ClassA
	) {}

	methodB(): string {
		return this.classA.methodA();
	}

	methodB2(): string {
		return 'def'
	}
}

class ClassC {
	constructor(
		private classB: ClassB
	) {}

	methodC(): string {
		return this.classB.methodB2();
	}
}

const classBMock = Substitute.for<ClassB>();
const classC = new ClassC(classBMock);

Typescript will complain about that last line because classBMock lacks a member called classA.

@ffMathy
Copy link
Owner

ffMathy commented Feb 24, 2019

Will investigate soon!

@ilancohen
Copy link

@ffMathy - I created a basic example, using your code.

@ffMathy
Copy link
Owner

ffMathy commented Feb 26, 2019

Fixed. Thanks for making the library better!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants